aboutsummaryrefslogtreecommitdiff
path: root/files/ru/learn/forms/styling_web_forms/index.html
blob: f8186549068c98b85019505437fd63ebfdddddfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
---
title: Стили HTML форм
slug: Learn/Forms/Styling_web_forms
translation_of: Learn/Forms/Styling_web_forms
original_slug: Learn/HTML/Forms/Styling_HTML_forms
---
<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/HTML_forms_in_legacy_browsers", "Learn/HTML/Forms/Advanced_styling_for_HTML_forms", "Learn/HTML/Forms")}}</p>

<p class="summary"><span class="seoSummary">В этой статье Вы узнает, как использовать CSS с HTML-формами, чтобы сделать их (надеюсь) более красивыми. Удивительно, но это может быть немного сложнее. По историческим и техническим причинам виджеты форм плохо сочетаются с CSS. Из-за этих трудностей многие разработчики предпочитают создавать свои собственные HTML-виджеты, чтобы получить контроль над своим внешним видом. Однако в современных браузерах веб-дизайнеры все больше контролируют дизайн элементов формы. Давайте приступим!</span></p>

<h2 id="Почему_так_сложно_стилизовать_виджеты_форм_с_помощью_CSS">Почему так сложно стилизовать виджеты форм с помощью CSS?</h2>

<p>На заре Интернета, примерно в 1995 году, в <a href="http://www.ietf.org/rfc/rfc1866.txt">HTML 2</a> были добавлены элементы управления формой. Из-за сложности виджетов форм разработчики решили полагаться на базовую операционную систему для управления ими и их рендеринга.</p>

<p>Несколько лет спустя был создан CSS, и то, что было технической необходимостью, то есть использование собственных виджетов для реализации элементов управления формой, стало требованием к стилю. В первые дни CSS, стилизация элементов управления формы не была приоритетом.</p>

<p>Поскольку пользователи привыкли к внешнему виду своих соответствующих платформ, поставщики браузеров неохотно делают элементы управления формами стилевыми; и по сей день все еще чрезвычайно трудно перестроить все элементы управления, чтобы сделать их стилизованными.</p>

<p>Даже сегодня ни один браузер полностью не реализует CSS 2.1. Однако со временем поставщики браузеров улучшили свою поддержку CSS для элементов формы, и, несмотря на плохую репутацию в отношении удобства использования, теперь вы можете использовать CSS для стилизации <a href="/en-US/docs/HTML/Forms">HTML форм</a>.</p>

<h3 id="Не_все_виджеты_созданы_равными_когда_задействован_CSS">Не все виджеты созданы равными, когда задействован CSS</h3>

<p>В настоящее время некоторые трудности остаются при использовании CSS с формами. Эти проблемы можно разделить на три категории:</p>

<h4 id="Хорошая">Хорошая</h4>

<p>Некоторые элементы могут быть стилизованы с небольшим количеством проблем на разных платформах. К ним относятся следующие структурные элементы:</p>

<ol>
 <li>{{HTMLElement("form")}}</li>
 <li>{{HTMLElement("fieldset")}}</li>
 <li>{{HTMLElement("label")}}</li>
 <li>{{HTMLElement("output")}}</li>
</ol>

<p>Сюда также входят все виджеты текстового поля (как однострочные, так и многострочные) и кнопки.</p>

<h4 id="Плохая">Плохая</h4>

<p>Некоторые элементы редко могут быть стилизованы, и могут потребовать некоторых сложных уловок, иногда требующих углубленных знаний CSS3.</p>

<p>Они включают в себя элемент {{HTMLElement ("legend")}}, но его нельзя правильно расположить на всех платформах. Флажки и переключатели также не могут быть стилизованы напрямую, однако, благодаря CSS3 вы можете обойти это. Контент {{htmlattrxref ("placeholder", "input")}} не может быть стилизован каким-либо стандартным способом, однако все браузеры, которые его реализуют, также реализуют собственные псевдо-элементы CSS или псевдоклассы, которые позволяют его стилизовать.</p>

<p>Мы опишем, как обрабатывать эти более конкретные случаи, в статье <a href="/en-US/docs/Advanced_styling_for_HTML_forms">«Расширенные стили для HTML-форм».</a></p>

<h4 id="The_ugly">The ugly</h4>

<p>Some elements simply can't be styled using CSS. These include: all advanced user interface widgets, such as range, color, or date controls; and all the dropdown widgets, including {{HTMLElement("select")}}, {{HTMLElement("option")}}, {{HTMLElement("optgroup")}} and {{HTMLElement("datalist")}} elements. The file picker widget is also known not to be stylable at all. The new {{HTMLElement("progress")}} and {{HTMLElement("meter")}} elements also fall in this category.</p>

<p>The main issue with all these widgets, comes from the fact that they have a very complex structure, and CSS is not currently expressive enough to style all the subtle parts of those widgets. If you want to customize those widgets, you have to rely on JavaScript to build a DOM tree you'll be able to style. We explore how to do this in the article <a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a>.</p>

<h2 id="Basic_styling">Basic styling</h2>

<p>To style <a href="/en-US/docs/HTML/Forms/Styling_HTML_forms#The_good" title="/en-US/docs/HTML/Forms/Styling_HTML_forms#The_good">elements that are easy to style</a> with CSS, you shouldn't face any difficulties, since they mostly behave like any other HTML element. However, the user-agent style sheet of every browser can be a little inconsistent, so there are a few tricks that can help you style them in an easier way.</p>

<h3 id="Search_fields">Search fields</h3>

<p>Search boxes are the only kind of text fields that can be a little tricky to style. On WebKit based browsers (Chrome, Safari, etc.), you'll have to tweak it with the <code>-webkit-appearance</code> proprietary property. We discuss this property further in the article: <a href="/en-US/docs/Advanced_styling_for_HTML_forms" title="/en-US/docs/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a>.</p>

<h4 id="Example">Example</h4>

<pre class="brush: html">&lt;form&gt;
  &lt;input type="search"&gt;
&lt;/form&gt;
</pre>

<pre class="brush: css">input[type=search] {
  border: 1px dotted #999;
  border-radius: 0;

  -webkit-appearance: none;
}</pre>

<p><img alt="This is a screenshot of a search filed on Chrome, with and without the use of -webkit-appearance" src="/files/4153/search-chrome-macos.png" style="border-style: solid; border-width: 1px; height: 107px; width: 179px;"></p>

<p>As you can see on this screenshot of the search field on Chrome, the two fields have a border set as in our example. The first field is rendered without using the <code>-webkit-appearance</code> property, whereas the second is rendered using <code>-webkit-appearance:none</code>. This difference is noticeable.</p>

<h3 id="Fonts_and_text">Fonts and text</h3>

<p>CSS font and text features can be used easily with any widget (and yes, you can use {{cssxref("@font-face")}} with form widgets). However, browsers' behaviors are often inconsistent. By default, some widgets do not inherit {{cssxref("font-family")}} and {{cssxref("font-size")}} from their parents. Many browsers use the system default appearance instead. To make your forms' appearance consistent with the rest of your content, you can add the following rules to your stylesheet:</p>

<pre class="brush: css">button, input, select, textarea {
  font-family : inherit;
  font-size   : 100%;
}</pre>

<p>The screenshot below shows the difference; on the left is the default rendering of the element in Firefox on Mac OS X, with the platform's default font style in use. On the right are the same elements, with our font harmonization style rules applied.</p>

<p><img alt="This is a screenshot of the main form widgets on Firefox on Mac OSX, with and without font harmonization" src="/files/4157/font-firefox-macos.png" style="border-style: solid; border-width: 1px; height: 234px; width: 420px;"></p>

<p>There's a lot of debate as to whether forms look better using the system default styles, or customized styles designed to match your content. This decision is yours to make, as the designer of your site, or Web application.</p>

<h3 id="Box_model">Box model</h3>

<p>All text fields have complete support for every property related to the CSS box model ({{cssxref("width")}}, {{cssxref("height")}}, {{cssxref("padding")}}, {{cssxref("margin")}}, and {{cssxref("border")}}). As before, however, browsers rely on the system default styles when displaying these widgets. It's up to you to define how you wish to blend them into your content. If you want to keep the native look and feel of the widgets, you'll face a little difficulty if you want to give them a consistent size.</p>

<p><strong>This is because each widget has their own rules for border, padding and margin.</strong> So if you want to give the same size to several different widgets, you have to use the {{cssxref("box-sizing")}} property:</p>

<pre class="brush: css">input, textarea, select, button {
  width : 150px;
  margin: 0;

  -webkit-box-sizing: border-box; /* For legacy WebKit based browsers */
     -moz-box-sizing: border-box; /* For legacy (Firefox &lt;29) Gecko based browsers */
          box-sizing: border-box;
}</pre>

<p><img alt="This is a screenshot of the main form widgets on Chrome on Windows 7, with and without the use of box-sizing." src="/files/4161/size-chrome-win7.png" style="border-style: solid; border-width: 1px; height: 213px; width: 358px;"></p>

<p>In the screenshot above, the left column is built without {{cssxref("box-sizing")}}, while the right column uses this property with the value <code>border-box</code>. Notice how this lets us ensure that all of the elements occupy the same amount of space, despite the platform's default rules for each kind of widget.</p>

<h3 id="Positioning">Positioning</h3>

<p>Positioning of HTML form widgets is generally not a problem; however, there are two elements you should take special note of:</p>

<h4 id="legend">legend</h4>

<p>The {{HTMLElement("legend")}} element is okay to style, except for positioning. In every browser, the {{HTMLElement("legend")}} element is positioned on top of the top border of its {{HTMLElement("fieldset")}} parent. There is absolutely no way to change it to be positioned within the HTML flow, away from the top border. You can, however, position it absolutely or relatively, using the {{cssxref("position")}} property. But otherwise it is part of the fieldset border.</p>

<p>Because the {{HTMLElement("legend")}} element is very important for accessibility reasons, it will be spoken by assistive technologies as part of the label of each form element inside the fieldset, it's quite often paired with a title, and then hidden in an accessible way. For example:</p>

<h5 id="HTML">HTML</h5>

<pre class="brush: html">&lt;fieldset&gt;
  &lt;legend&gt;Hi!&lt;/legend&gt;
  &lt;h1&gt;Hello&lt;/h1&gt;
&lt;/fieldset&gt;</pre>

<h5 id="CSS">CSS</h5>

<pre class="brush: css">legend {
  width: 1px;
  height: 1px;
  overflow: hidden;
}</pre>

<h4 id="textarea">textarea</h4>

<p>By default, all browsers consider the {{HTMLElement("textarea")}} element to be an inline block, aligned to the text bottom line. This is rarely what we actually want to see. To change from <code>inline-block</code> to <code>block</code>, it's pretty easy to use the {{cssxref("display")}} property. But if you want to use it inline, it's common to change the vertical alignment:</p>

<pre class="brush: css">textarea {
  vertical-align: top;
}</pre>

<h2 id="Example_2">Example</h2>

<p>Let's look at a concrete example of how to style an HTML form. This will help make a lot of these ideas clearer. We will build the following "postcard" contact form:</p>

<p><img alt="This is what we want to achieve with HTML and CSS" src="/files/4149/screenshot.png" style="border-style: solid; border-width: 1px; height: 249px; width: 370px;"></p>

<p>If you want to follow along with this example, make a local copy of our <a href="https://github.com/mdn/learning-area/blob/master/html/forms/postcard-example/postcard-start.html">postcard-start.html file</a>, and follow the below instructions.</p>

<h3 id="The_HTML">The HTML</h3>

<p>The HTML is only slightly more involved than the example we used in <a href="/en-US/docs/HTML/Forms/My_first_HTML_form" title="/en-US/docs/HTML/Forms/My_first_HTML_form">the first article of this guide</a>; it just has a few extra IDs and a title.</p>

<pre class="brush: html">&lt;form&gt;
  &lt;h1&gt;to: Mozilla&lt;/h1&gt;

  &lt;div id="from"&gt;
    &lt;label for="name"&gt;from:&lt;/label&gt;
    &lt;input type="text" id="name" name="user_name"&gt;
  &lt;/div&gt;

  &lt;div id="reply"&gt;
    &lt;label for="mail"&gt;reply:&lt;/label&gt;
    &lt;input type="email" id="mail" name="user_email"&gt;
  &lt;/div&gt;

  &lt;div id="message"&gt;
    &lt;label for="msg"&gt;Your message:&lt;/label&gt;
    &lt;textarea id="msg" name="user_message"&gt;&lt;/textarea&gt;
  &lt;/div&gt;

  &lt;div class="button"&gt;
    &lt;button type="submit"&gt;Send your message&lt;/button&gt;
  &lt;/div&gt;
&lt;/form&gt;</pre>

<p>Add the above code into the body of your HTML.</p>

<h3 id="Organizing_your_assets">Organizing your assets</h3>

<p>This is where the fun begins! Before we start coding, we need three additional assets:</p>

<ol>
 <li>The postcard <a href="/files/4151/background.jpg" title="The postcard background">background</a> — download this image and save it in the same directory as your working HTML file.</li>
 <li>A typewriter font: <a href="http://www.fontsquirrel.com/fonts/Secret-Typewriter" rel="external" title="http://www.fontsquirrel.com/fonts/Secret-Typewriter">The "Secret Typewriter" font from fontsquirrel.com</a> — download the TTF file into the same directory as above.</li>
 <li>A handdrawn font: <a href="http://www.fontsquirrel.com/fonts/Journal" rel="external" title="http://www.fontsquirrel.com/fonts/Journal">The "Journal" font from fontsquirrel.com</a> — download the TTF file into the same directory as above.</li>
</ol>

<p>Your fonts need some more processing before you start:</p>

<ol>
 <li>Go to the fontsquirrel <a href="https://www.fontsquirrel.com/tools/webfont-generator">Webfont Generator</a>.</li>
 <li>Using the form, upload both your font files and generate a webfont kit. Download the kit to your computer.</li>
 <li>Unzip the provided zip file.</li>
 <li>Inside the unzipped contents you will find two <code>.woff</code> files and two <code>.woff2</code> files. Copy these four files into a directory called fonts, in the same directory as before. We are using two different files for each font to maximise browser compatibility; see our <a href="/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Web fonts</a> article for a lot more information.</li>
</ol>

<h3 id="The_CSS">The CSS</h3>

<p>Now we can dig into the CSS for the example. Add all the code blocks shown below inside the {{htmlelement("style")}} element, one after another.</p>

<p>First, we prepare the ground by defining our {{cssxref("@font-face")}} rules, all the basics on the {{HTMLElement("body")}} element, and the {{HTMLElement("form")}} element:</p>

<pre class="brush: css">@font-face {
    font-family: 'handwriting';
    src: url('fonts/journal-webfont.woff2') format('woff2'),
         url('fonts/journal-webfont.woff') format('woff');
    font-weight: normal;
    font-style: normal;
}

@font-face {
    font-family: 'typewriter';
    src: url('fonts/veteran_typewriter-webfont.woff2') format('woff2'),
         url('fonts/veteran_typewriter-webfont.woff') format('woff');
    font-weight: normal;
    font-style: normal;
}

body {
  font  : 21px sans-serif;

  padding : 2em;
  margin  : 0;

  background : #222;
}

form {
  position: relative;

  width  : 740px;
  height : 498px;
  margin : 0 auto;

  background: #FFF url(background.jpg);
}</pre>

<p>Now we can position our elements, including the title and all the form elements:</p>

<pre class="brush: css">h1 {
  position : absolute;
  left : 415px;
  top  : 185px;

  font : 1em "typewriter", sans-serif;
}

#from {
  position: absolute;
  left : 398px;
  top  : 235px;
}

#reply {
  position: absolute;
  left : 390px;
  top  : 285px;
}

#message {
  position: absolute;
  left : 20px;
  top  : 70px;
}</pre>

<p>That's where we start working on the form elements themselves. First, let's ensure that the {{HTMLElement("label")}}s are given the right font:</p>

<pre class="brush: css">label {
  font : .8em "typewriter", sans-serif;
}</pre>

<p>The text fields require some common rules. Simply put, we remove their {{cssxref("border","borders")}} and {{cssxref("background","backgrounds")}}, and redefine their {{cssxref("padding")}} and {{cssxref("margin")}}:</p>

<pre class="brush: css">input, textarea {
  font    : .9em/1.5em "handwriting", sans-serif;

  border  : none;
  padding : 0 10px;
  margin  : 0;
  width   : 240px;

  background: none;
}</pre>

<p>When one of these fields gains focus, we highlight them with a light grey, transparent, background. Note that it's important to add the {{cssxref("outline")}} property, in order to remove the default focus highlight added by some browsers:</p>

<pre class="brush: css">input:focus, textarea:focus {
  background   : rgba(0,0,0,.1);
  border-radius: 5px;
  outline      : none;
}</pre>

<p>Now that our text fields are complete, we need to adjust the display of the single and multiple line text fields to match, since they won't typically look the same using the defaults.</p>

<p>The single-line text field needs some tweaks to render nicely in Internet Explorer. Internet Explorer does not define the height of the fields based on the natural height of the font (which is the behavior of all other browsers). To fix this, we need to add an explicit height to the field, as follows:</p>

<pre class="brush: css">input {
    height: 2.5em; /* for IE */
    vertical-align: middle; /* This is optional but it makes legacy IEs look better */
}</pre>

<p>{{HTMLElement("textarea")}} elements default to being rendered as a block element. The two important things here are the {{cssxref("resize")}} and {{cssxref("overflow")}} properties. Because our design is a fixed-size design, we will use the <code>resize</code> property to prevent users from resizing our multi-line text field. The {{cssxref("overflow")}} property is used to make the field render more consistently across browsers. Some browsers default to the value <code>auto</code>, while some default to the value <code>scroll</code>. In our case, it's better to be sure every one will use <code>auto</code>:</p>

<pre class="brush: css">textarea {
  display : block;

  padding : 10px;
  margin  : 10px 0 0 -10px;
  width   : 340px;
  height  : 360px;

  resize  : none;
  overflow: auto;
}</pre>

<p>The {{HTMLElement("button")}} element is really convenient with CSS; you can do whatever you want, even using <a href="/en-US/docs/CSS/Pseudo-elements" title="/en-US/docs/CSS/Pseudo-elements">pseudo-elements</a>:</p>

<pre class="brush: css">button {
  position     : absolute;
  left         : 440px;
  top          : 360px;

  padding      : 5px;

  font         : bold .6em sans-serif;
  border       : 2px solid #333;
  border-radius: 5px;
  background   : none;

  cursor       : pointer;

-webkit-transform: rotate(-1.5deg);
   -moz-transform: rotate(-1.5deg);
    -ms-transform: rotate(-1.5deg);
     -o-transform: rotate(-1.5deg);
        transform: rotate(-1.5deg);
}

button:after {
  content: " &gt;&gt;&gt;";
}

button:hover,
button:focus {
  outline   : none;
  background: #000;
  color   : #FFF;
}</pre>

<p>And voila!</p>

<div class="note">
<p><strong>Note</strong>: If your example does not work quite like you expected and you want to check it against our version, you can find it on GitHub — see it <a href="https://mdn.github.io/learning-area/html/forms/postcard-example/">running live</a> (also see <a href="https://github.com/mdn/learning-area/tree/master/html/forms/postcard-example">the source code</a>).</p>
</div>

<h2 id="Conclusion">Conclusion</h2>

<p>As you can see, as long as we want to build forms with just text fields and buttons, it's easy to style them using CSS. If you want to know more of the little CSS tricks that can make your life easier when working with form widgets, take a look at the form part of <a href="http://necolas.github.com/normalize.css" rel="external" title="http://necolas.github.com/normalize.css">the normalize.css project</a>.</p>

<p><a href="/en-US/docs/Web/Guide/HTML/Forms/Advanced_styling_for_HTML_forms" title="/en-US/docs/Advanced_styling_for_HTML_forms">In the next article</a>, we will see how to handle form widgets which fall in the "bad" and "ugly" categories.</p>

<p>{{PreviousMenuNext("Learn/HTML/Forms/HTML_forms_in_legacy_browsers", "Learn/HTML/Forms/Advanced_styling_for_HTML_forms", "Learn/HTML/Forms")}}</p>

<h2 id="In_this_module">In this module</h2>

<ul>
 <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li>
 <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li>
</ul>