aboutsummaryrefslogtreecommitdiff
path: root/files/ru/learn/forms/form_validation/index.html
blob: d137b8841d455858981046919ab8fef07842e87c (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
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
---
title: Валидация форм на стороне клиента
slug: Learn/Forms/Form_validation
tags:
  - Новичку
  - Пример
  - Формы
  - Гайд
  - HTML
  - JavaScript
  - Изучение
  - Web
  - regex
---
<div>{{LearnSidebar}}</div>

<div>{{PreviousMenuNext("Learn/Forms/UI_pseudo-classes", "Learn/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}</div>

<p>Перед отправкой данных на сервер важно убедиться, что все обязательные поля формы заполнены данными в корректном формате. Это называется <strong>валидацией на стороне клиента</strong> и помогает убедиться, что данные, введённые в каждый элемент формы, соответствуют требованиям. Данная статья проведёт вас через основные концепци и примеры валидации на стороне клиента.</p>

<table class="learn-box standard-table">
 <tbody>
  <tr>
   <th scope="row">Начальные требования:</th>
   <td>Владение компьютером, достаточное понимание <a href="/ru/docs/Learn/HTML">HTML</a>, <a href="/ru/docs/Learn/CSS">CSS</a>, и <a href="/ru/docs/Learn/JavaScript">JavaScript</a>.</td>
  </tr>
  <tr>
   <th scope="row">Цель:</th>
   <td>Понять, что такое валидация на стороне клиента, почему это важно и как применять различные техники для её реализации.</td>
  </tr>
 </tbody>
</table>

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

<p>Однако, <em>не следует рассматривать</em> валидацию на стороне клиента как достаточную меру безопасности! Любые данные, отправляемые через форму, необходимо <em>дополнительно</em> проверять на безопасность и <em>на стороне сервера</em>, поскольку валидацию на стороне клиента достаточно просто обойти и она может не остановить злоумышленников. Чтобы лучше понимать потенциальные угрозы, рекомендуем ознакомиться с разделом <a href="/ru/docs/Learn/Server-side/First_steps/Website_security">Безопасность вебсайтов</a>; валидация на стороне сервера выходит за рамки этого модуля, но о ней следует помнить.</p>

<h2 id="What_is_form_validation">Что такое валидация формы?</h2>

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

<ul>
 <li>"Обязательное поле" (Вы не можете оставить поле пустым).</li>
 <li>"Пожалуйста, введите номер телефона в формате xxx-xxxx" (Чтобы данные считались корректными, их необходимо указать в определённом формате).</li>
 <li>"Пожалуйста, введите корректный email-адрес" (вы ввели данные в неправильном формате).</li>
 <li>"Длина пароля должна быть от 8 до 30 символов и включать одну заглавную букву, один символ, и одну цифру." (Требования к формату данных достаточно конкретные).</li>
</ul>

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

<p>Если формат корректен, приложение позволяет отправить данные на сервер и (обычно) сохранить в базу данных; в противном случае выводится сообщение с описанием того, что нужно исправить, позволяя ввести данные снова.</p>

<p>Мы хотим максимально упростить заполнение веб-форм. Тогда почему мы настаиваем валидации данных? На это есть три основные причины:</p>

<ul>
 <li><strong>Мы хотим получать правильные данные в правильном формате.</strong> Наши приложения не будут работать должным образом, если данные от пользователей хранятся в неправильном формате, некорректны сами по себе или вовсе пропущены.</li>
 <li><strong>Мы хотим защитить данные пользователей</strong>. Принуждение пользователей вводить надёжные пароли облегчает защиту их аккаунтов.</li>
 <li><strong>Мы хотим защитить себя</strong>. Существует множество способов, позволяющих злоумышленникам с помощью незащищённых форм навредить приложению (смотрите <a href="/ru/docs/Learn/Server-side/First_steps/Website_security">Безопасность вебсайтов</a>).<br>
  {{warning("Никогда не доверяйте данным, передаваемым на сервер клиентской программой. Даже если ваша форма правильно валидируется и не допустит введение потенциально вредоносных данных на стороне клиента, злоумышленники по-прежнему могут изменить сетевой запрос.")}}</li>
</ul>

<h2 id="Different_types_of_client-side_validation">Типы валидации на стороне клиента</h2>

<p>Существует два типа валидации на стороне клиента, с которыми вы столкнётесь в Интернете:</p>

<ul>
 <li><strong>Встроенная валидация форм</strong> использует функционал валидации HTML5, который мы неоднократно обсуждали в этом модуле. HTML5-валидация обычно не требует большого количества JavaScript-кода и демонстрирует лучшую производительность, но не настолько настраиваема, как валидация с помощью JavaScript.</li>
 <li><strong>JavaScript-валидация</strong> кодируется с помощью JavaScript. Она полностью настраиваема, но требует программирования всей логики (или использования библиотеки).</li>
</ul>

<h2 id="Using_built-in_form_validation">Использование встроенной валидации форм</h2>

<p>Одной из самых важных функций <a href="/en-US/docs/Learn/Forms/HTML5_input_types">элементов форм HTML5</a> является способность валидировать бóльшую часть пользовательских данных без использования JavaScript. Это выполняется с помощью атрибутов валидации у элементов формы. Многие из них мы уже рассмотрели в этом курсе:</p>

<ul>
 <li><code><a href="/en-US/docs/Web/HTML/Attributes/required">required</a></code>: Определяет, что для отправки формы данное поле предварительно должно быть заполнено.</li>
 <li><code><a href="/en-US/docs/Web/HTML/Attributes/minlength">minlength</a></code> и <code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>: Задаёт минимальную и максимальную длину текстовых данных (строк)</li>
 <li><code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code> и <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code>: Задаёт минимальное и максимальное значение для поля, расчитанного на числовой тип данных</li>
 <li><code>type</code>: Определяет тип данных, на который рассчитано поле: число, email-адрес или какой-то другой предустановленный тип</li>
 <li><code><a href="/ru/docs/Web/HTML/Attributes/pattern">pattern</a></code>: С помощью <a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions">регулярного выражения</a>, определяет шаблон, которому должны соответствовать вводимые данные.</li>
</ul>

<p>Если данные, введённые в поле формы, соответствуют правилам перечисленных выше атрибутов, они считаются валидными, если нет — не валидными</p>

<p>Когда элемент валиден, справедливы следующие утверждения:</p>

<ul>
 <li>Элемент соответствует CSS-псевдоклассу {{cssxref(":valid")}}, позволяющему стилизовать только валидные элементы.</li>
 <li>Если пользователь пытается отправить данные, браузер отправит форму при условии, что ничто другое (например, JavaScript) не помешает ему это сделать</li>
</ul>

<p>Когда элемент не валиден, справедливы следующие утверждения:</p>

<ul>
 <li>Элемент соответствует CSS-псевдоклассу {{cssxref(":invalid")}} или, в зависимости от ошибки, другим псевдоклассам (например, {{cssxref(":out-of-range")}}), которые позволяют применять определённые стили к элементам, не являющимся валидными.</li>
 <li>Если пользователь пытается отправить данные, браузер заблокирует форму и выведет сообщение об ошибке.</li>
</ul>

<div class="notecard note">
<p><strong>Примечание</strong>: Существует ошибки, которые не позволяют отправлять форму, в частности {{domxref('validityState.badInput', 'badInput')}}, {{domxref('validityState.patternMismatch','patternMismatch')}}, {{domxref('validityState.rangeOverflow','rangeOverflow')}} или {{domxref('validityState.rangeUnderflow','rangeUnderflow')}}, {{domxref('validityState.stepMismatch','stepMismatch')}}, {{domxref('validityState.tooLong','tooLong')}} или {{domxref('validityState.tooShort','tooShort')}}, {{domxref('validityState.typeMismatch','typeMismatch')}}, {{domxref('validityState.valueMissing','valueMissing')}}, или {{domxref('validityState.customError','customError')}}.</p>
</div>

<h2 id="Built-in_form_validation_examples">Примеры встроенной валидации форм</h2>

<p>В этом разделе мы протестируем некоторые из атрибутов, которые обсуждали выше.</p>

<h3 id="Simple_start_file">Простой начальный файл</h3>

<p>Давайте начнём с простого примера: поле, позволяющее указать своё предпочтение — банан или вишня. Этот пример включает обычное текстовое поле {{HTMLElement("input")}}, связанный с ним элемент {{htmlelement("label")}} и кнопку отправки формы {{htmlelement("button")}}. Исходный код можно найти на GitHub по адресу <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a>, а ниже приведён рабочий пример.</p>

<pre class="brush: html">&lt;form&gt;
  &lt;label for="choose"&gt;Would you prefer a banana or cherry?&lt;/label&gt;
  &lt;input id="choose" name="i_like"&gt;
  &lt;button&gt;Submit&lt;/button&gt;
&lt;/form&gt;</pre>

<pre class="brush: css">input:invalid {
  border: 2px dashed red;
}

input:valid {
  border: 2px solid black;
}</pre>

<p>{{EmbedLiveSample("Simple_start_file", "100%", 80)}}</p>

<p>Для начала скопируйте файл <code>fruit-start.html</code> в новую папку на вашем жёстком диске.</p>

<h3 id="The_required_attribute">Атрибут required</h3>

<p>Самым простым в HTML5-валидации является атрибут <code><a href="/en-US/docs/Web/HTML/Attributes/required">required</a></code>. Добавьте его к элементу, чтобы сделать заполнение обязательным. Элемент с данным атрибутом соответствует CSS-псевдоклассу {{cssxref(':required')}}, а если поле ввода пустое, вместо отправки формы отобразится сообщение об ошибке. Пока поле пустое, оно также будет соответствовать CSS-псевдоклассу {{cssxref(':invalid')}}.</p>

<p>Добавьте к полю атрибут <code>required</code>, как показано ниже.</p>

<pre class="brush: html">&lt;form&gt;
  &lt;label for="choose"&gt;Would you prefer a banana or cherry? (required)&lt;/label&gt;
  &lt;input id="choose" name="i_like" required&gt;
  &lt;button&gt;Submit&lt;/button&gt;
&lt;/form&gt;</pre>

<p>Обратите внимание на CSS, который включён в файл примера:</p>

<pre class="brush: css">input:invalid {
  border: 2px dashed red;
}

input:invalid:required {
  background-image: linear-gradient(to right, pink, lightgreen);
}

input:valid {
  border: 2px solid black;
}</pre>

<p>Данный CSS задаёт полю красную пунктирную рамку, когда оно не валидно, а когда валидно — сплошную чёрную. Мы также добавили фоновый градиент для обязательных не валидных полей. Проверьте новое поведение в примере ниже:</p>

<p>{{EmbedLiveSample("The_required_attribute", "100%", 80)}}</p>

<div class="notecard note">
<p><strong>Примечание</strong>: Рабочий пример можно найти на GitHub по адресу <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-required.html">fruit-validation.html</a> (отдельно можно найти <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-required.html">исходный код</a>.)</p>
</div>

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

<p>Наличие атрибута <code>required</code> у любого элемента, который его поддерживает, означает, что элемент соответствует CSS-псевдоклассу {{cssxref(':required')}}, независимо от того, имеет он значение или нет. Если элемент {{HTMLElement("input")}} не содержит значение, он будет соответствовать псевдоклассу {{cssxref(':invalid')}}.</p>

<div class="notecard note">
<p><strong>Примечание</strong>: Для повышения удобства взаимодействия указывайте пользователям, какие поля являются обязательными. К тому же, этого требует руководство по обеспечению <a href="/ru/docs/Learn/Accessibility">доступности</a> WCAG. Требуйте обязательного ввода только тех данных, которые вам действительно нужны: например, так ли важно знать пол или должность пользователя?</p>
</div>

<h3 id="Validating_against_a_regular_expression">Валидация с помощью регулярного выражения</h3>

<p>Ещё одной полезной функцией валидации является атрибут <a href="/ru/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>, который в виде значения принимает <a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions">Регулярное выражение</a>. Регулярное выражение (regex) — это шаблон, который может быть использован для сопоставления набора символов в текстовой строке, поэтому они идеально подходят для валидации формы и используются для множества других целей в JavaScript.</p>

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

<ul>
 <li><code>a</code> — Соответствует одному символу <code>a</code> (не <code>b</code>, не <code>aa</code>, и так далее).</li>
 <li><code>abc</code> — Соответствует символу <code>a</code>, за которой следует <code>b</code>, за которой следует <code>c</code>.</li>
 <li><code>ab?c</code> — Соответствует символу <code>a</code>, за которым опционально может следовать <code>b</code>, за которым следует <code>c</code>. ( <code>ac</code> или <code>abc</code>)</li>
 <li><code>ab*c</code> — Соответствует символу <code>a</code>, за которым опционально может следовать любое количество символов <code>b</code>, за которыми следует <code>c</code>. ( <code>ac</code> , <code>abc</code>, <code>abbbbbc</code>, и так далее).</li>
 <li><code>a|b</code> — Соответствует символу <code>a</code> или <code>b</code>.</li>
 <li><code>abc|xyz</code> — Соответствует в точности <code>abc</code> или в точности <code>xyz</code> (но не <code>abcxyz</code> или <code>a</code> или <code>y</code>, и так далее).</li>
</ul>

<p>Есть еще много возможностей, которые мы не упомянули. Полный список со множеством примеров можно найти в документации по <a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions">Регулярным выражениям</a></p>

<p>Давайте рассмотрим пример. Добавьте в атрибут <a href="/ru/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a> следующий шаблон:</p>

<pre class="brush: html">&lt;form&gt;
  &lt;label for="choose"&gt;Would you prefer a banana or a cherry?&lt;/label&gt;
  &lt;input id="choose" name="i_like" required pattern="[Bb]anana|[Cc]herry"&gt;
  &lt;button&gt;Submit&lt;/button&gt;
&lt;/form&gt;
</pre>

<div class="hidden">
<pre class="brush: css">input:invalid {
  border: 2px dashed red;
}

input:valid {
  border: 2px solid black;
}</pre>
</div>

<p>Это даёт нам следующее обновление — опробуйте его:</p>

<p>{{EmbedLiveSample("Validating_against_a_regular_expression", "100%", 80)}}</p>

<div class="notecard note">
<p><strong>Примечание</strong>: Рабочий пример можно найти на GitHub по адресу <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-pattern.html">fruit-pattern.html</a> (<a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-pattern.html">исходный код</a>.)</p>
</div>

<p>В этом примере элемент {{HTMLElement("input")}} принимает одно из четырёх возможных значений: строку "banana", "Banana", "cherry", или "Cherry". Регулярные выражения чувствительны к регистру, но с помощью шаблона "Aa", вложенного в квадратные скобки, мы сделали поддержку написания слова как с большой, так и с маленькой буквы.</p>

<p>Подставьте в атрибут <a href="/ru/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a> приведённые выше примеры регулярных выражений, и посмотрите, как это повлияет на валидацию введённого в поле значения. Попробуйте написать свои шаблоны проверки и посмотрите, что получится. По возможности, делайте их связанными с фруктами, чтобы примеры имели смысл.</p>

<p>Если не пустое значение элемента {{HTMLElement("input")}} не соответствует шаблону регулярного выражения, <code>input</code> будет соответствовать псевдоклассу {{cssxref(':invalid')}}.</p>

<div class="notecard note">
<p><strong>Примечание:</strong> Некоторым типам элементов {{HTMLElement("input")}} для валидации с помощью регулярного выражения не требуется атрибут <a href="/ru/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>. Например, поле с типом <code>email</code> валидирует значение по шаблону одного email-адреса или, если присутствует атрибут <a href="/en-US/docs/Web/HTML/Attributes/multiple"><code>multiple</code></a>, шаблону списка email-адресов, разделённых запятыми.</p>
</div>

<div class="notecard note">
<p><strong>Примечание</strong>: Элемент {{HTMLElement("textarea")}} не поддерживает атрибут <a href="/ru/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>.</p>
</div>

<h3 id="Constraining_the_length_of_your_entries">Ограничение длины вводимых значений</h3>

<p>Можно ограничить максимально допустимое количество символов для текстовых полей {{HTMLElement("input")}} или {{HTMLElement("textarea")}} используя атрибуты <a href="/en-US/docs/Web/HTML/Attributes/minlength"><code>minlength</code></a> и <code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>. Поле будет не валидным, если количество символов его содержимого будет меньше <a href="/en-US/docs/Web/HTML/Attributes/minlength"><code>minlength</code></a> или больше <code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>.</p>

<p>Зачастую браузеры не позволяют пользователям вводить в текстовое поле значение, длина которого превышает максимально допустимую. Можно существенно повысить удобство использования, если помимо ограничения в атрибуте <code>maxlength</code> добавить доступный индикатор, отображающий текущее и максимально допустимое количество символов, что даст пользователю возможность уместить содержимое в заданные рамки. Хорошим примером является окно написания твита в Twitter. Для реализации такого функционала можно использовать JavaScript, включая <a href="https://github.com/mimo84/bootstrap-maxlength">решения, использующие <code>maxlength</code></a>.</p>

<h3 id="Constraining_the_values_of_your_entries">Ограничение допустимых значений</h3>

<p>В полях, предназначеннх для ввода чисел (например, <code><a href="/ru/docs/Web/HTML/Element/input/number">&lt;input type="number"&gt;</a></code>), диапазон допустимых значений можно определить с помощью атрибутов <code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code> и <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code>. Если поле содержит значение за пределами данного диапазона, оно будет не валидным.</p>

<p>Давайте рассмотрим другой пример. Создайте новую копию файла <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a>.</p>

<p>Содержимое элемента <code>&lt;body&gt;</code> замените на:</p>

<pre class="brush: html">&lt;form&gt;
  &lt;div&gt;
    &lt;label for="choose"&gt;Would you prefer a banana or a cherry?&lt;/label&gt;
    &lt;input type="text" id="choose" name="i_like" required minlength="6" maxlength="6"&gt;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;label for="number"&gt;How many would you like?&lt;/label&gt;
    &lt;input type="number" id="number" name="amount" value="1" min="1" max="10"&gt;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;button&gt;Submit&lt;/button&gt;
  &lt;/div&gt;
&lt;/form&gt;</pre>

<ul>
 <li>Здесь мы в полю с типом <code>text</code> атрибутам <code>minlength</code> и <code>maxlength</code>, задали одинаковое значение 6, что соответствует количеству символов в словах banana и cherry.</li>
 <li>В поле с типом <code>number</code> атрибуту <code>min</code> мы задали значение 1, а атрибуту <code>max</code> значение 10. При вводе чисел за пределами данного диапазона, поле будет становиться не валидным; с помощью стрелок увеличения/уменьшения пользователи не смогут выйти за границы диапазона. Текущее поле не является обязательным для заполнения, поэтому даже после очистки будет оставаться валидным.</li>
</ul>

<div class="hidden">
<pre class="brush: css">input:invalid {
  border: 2px dashed red;
}

input:valid {
  border: 2px solid black;
}

div {
  margin-bottom: 10px;
}</pre>
</div>

<p>Демонстрационный пример:</p>

<p>{{EmbedLiveSample("Constraining_the_values_of_your_entries", "100%", 100)}}</p>

<div class="notecard note">
<p><strong>Примечание</strong>: Рабочий пример можно найти на GitHub по адресу <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-length.html">fruit-length.html</a> (<a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-length.html">исходный код</a>.)</p>
</div>

<div class="notecard note">
<p><strong>Примечание</strong>: <code>&lt;input type="number"&gt;</code> (и другие типы, такие как <code>range</code> и <code>date</code>) могут также принимать атрибут <a href="/en-US/docs/Web/HTML/Attributes/step"><code>step</code></a>, который задаёт шаг увеличения или уменьшения значения при использовании кнопок вверх и вниз. В примере выше мы явно не указывали атрибут <code>step</code>, поэтому он получает значение по умолчанию, равное <code>1</code>. Это значит, что дробные числа, такие как 3.2, будут не валидными.</p>
</div>

<h3 id="Full_example">Полный пример</h3>

<p>Ниже представлен полный пример, демонстрирующий использование встроенного функционала валидации. Сначала немного HTML:</p>

<pre class="brush: html">&lt;form&gt;
  &lt;p&gt;
    &lt;fieldset&gt;
      &lt;legend&gt;Do you have a driver's license?&lt;abbr title="This field is mandatory" aria-label="required"&gt;*&lt;/abbr&gt;&lt;/legend&gt;
      &lt;!-- Так как в группе радио-кнопок, имеющих одинаковое имя, выбранной может быть
          только одна, то и атрибут "required" достаточно задать хотя бы одной кнопке,
          чтобы сделать всю группу обязательной для заполнения --&gt;
      &lt;input type="radio" required name="driver" id="r1" value="yes"&gt;&lt;label for="r1"&gt;Yes&lt;/label&gt;
      &lt;input type="radio" required name="driver" id="r2" value="no"&gt;&lt;label for="r2"&gt;No&lt;/label&gt;
    &lt;/fieldset&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;label for="n1"&gt;How old are you?&lt;/label&gt;
    &lt;!-- Атрибут "pattern" может выступать фолбэком для браузеров, которые
        не поддерживают поля ввода c числовым типом данных. Те браузеры,
        которые такие поля поддерживают, будут просто игнорировать его.
        Как раз, ниже атрибут "pattern" выполняет роль фолбека.
     --&gt;
    &lt;input type="number" min="12" max="120" step="1" id="n1" name="age"
           pattern="\d+"&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;label for="t1"&gt;What's your favorite fruit?&lt;abbr title="This field is mandatory" aria-label="required"&gt;*&lt;/abbr&gt;&lt;/label&gt;
    &lt;input type="text" id="t1" name="fruit" list="l1" required
           pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range"&gt;
    &lt;datalist id="l1"&gt;
      &lt;option&gt;Banana&lt;/option&gt;
      &lt;option&gt;Cherry&lt;/option&gt;
      &lt;option&gt;Apple&lt;/option&gt;
      &lt;option&gt;Strawberry&lt;/option&gt;
      &lt;option&gt;Lemon&lt;/option&gt;
      &lt;option&gt;Orange&lt;/option&gt;
    &lt;/datalist&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;label for="t2"&gt;What's your e-mail address?&lt;/label&gt;
    &lt;input type="email" id="t2" name="email"&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;label for="t3"&gt;Leave a short message&lt;/label&gt;
    &lt;textarea id="t3" name="msg" maxlength="140" rows="5"&gt;&lt;/textarea&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;button&gt;Submit&lt;/button&gt;
  &lt;/p&gt;
&lt;/form&gt;</pre>

<p>И немного CSS для стилизации HTML:</p>

<pre class="brush: css">form {
  font: 1em sans-serif;
  max-width: 320px;
}

p &gt; label {
  display: block;
}

input[type="text"],
input[type="email"],
input[type="number"],
textarea,
fieldset {
  width : 100%;
  border: 1px solid #333;
  box-sizing: border-box;
}

input:invalid {
  box-shadow: 0 0 5px 1px red;
}

input:focus:invalid {
  box-shadow: none;
}</pre>

<p>Получим следующее:</p>

<p>{{EmbedLiveSample("Full_example", "100%", 420)}}</p>

<p>В статье <a href="/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation#validation-related_attributes">Атрибуты валидации</a> можно найти полный список атрибутов, которые можно использовать для ограничения допустимых значений ввода и типов полей <code>input</code>, которые их поддерживают.</p>

<div class="notecard note">
<p><strong>Примечание</strong>: Рабочий пример можно найти на GitHub по адресу <a href="https://mdn.github.io/learning-area/html/forms/form-validation/full-example.html">full-example.html</a> (<a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/full-example.html">исходный код</a>.)</p>
</div>

<h2 id="Validating_forms_using_JavaScript">Валидация форм с помощью JavaScript</h2>

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

<h3 id="The_Constraint_Validation_API">Constraint Validation API</h3>

<p>Большинство браузеров поддерживают <a href="/en-US/docs/Web/API/Constraint_validation">Constraint Validation API</a>, который состоит из набора свойств и методов, доступных на DOM-интерфейсах следующих элементов форм:</p>

<ul>
 <li><code><a href="/ru/docs/Web/API/HTMLButtonElement">HTMLButtonElement</a></code> (представляет элемент <code><a href="/ru/docs/Web/HTML/Element/button">&lt;button&gt;</a></code>)</li>
 <li><code><a href="/en-US/docs/Web/API/HTMLFieldSetElement">HTMLFieldSetElement</a></code> (представляет элемент <code><a href="/ru/docs/Web/HTML/Element/fieldset">&lt;fieldset&gt;</a></code>)</li>
 <li><code><a href="/ru/docs/Web/API/HTMLInputElement">HTMLInputElement</a></code> (представляет элемент <code><a href="/ru/docs/Web/HTML/Element/input">&lt;input&gt;</a></code>)</li>
 <li><code><a href="/en-US/docs/Web/API/HTMLOutputElement">HTMLOutputElement</a></code> (представляет элемент <code><a href="/ru/docs/Web/HTML/Element/output">&lt;output&gt;</a></code>)</li>
 <li><code><a href="/ru/docs/Web/API/HTMLSelectElement">HTMLSelectElement</a></code> (представляет элемент <code><a href="/ru/docs/Web/HTML/Element/select">&lt;select&gt;</a></code>)</li>
 <li><code><a href="/en-US/docs/Web/API/HTMLTextAreaElement">HTMLTextAreaElement</a></code> (представляет элемент <code><a href="/en-US/docs/Web/HTML/Element/textarea">&lt;textarea&gt;</a></code>)</li>
</ul>

<p id="Constraint_validation_API_properties">Для перечисленных выше элементов Constraint Validation API  делает доступными следующие свойства.</p>

<ul>
 <li><code>validationMessage</code>: Возвращает локализованное сообщение, описывающее ограничения валидации (если таковые имеются), которым не удовлетворяет определённый элемент. Если элемент не участвует в валидации (<code>willValidate</code> установлено в <code>false</code>) или значение элемента удовлетворяет установленным ограничениям (является валидным), будет возвращена пустая строка.</li>
 <li><code>validity</code>: Возвращает объект <code>ValidityState</code>, который содержит несколько свойств, описывающих состояние валидности элемента. Подробное описание всех свойств доступности можно найти на странице справочника {{domxref("ValidityState")}}; ниже приведён список наиболее используемых:
  <ul>
   <li>{{domxref("ValidityState.patternMismatch", "patternMismatch")}}: Возвращает <code>true</code>, если значение не соответствует шаблону, указанному в атрибуте {{htmlattrxref("pattern", "input")}}, и <code>false</code> если соответствует. Если true, элемент соответствует CSS-псевдоклассу {{cssxref(":invalid")}}.</li>
   <li>{{domxref("ValidityState.tooLong", "tooLong")}}: Возвращает <code>true</code>, если значение длиннее максимальной длины, указанной в атрибуте {{htmlattrxref("maxlength", "input")}}, и <code>false</code> если оно короче или равно ей. Если true, элемент соответствует CSS-псевдоклассу {{cssxref(":invalid")}}.</li>
   <li>{{domxref("ValidityState.tooShort", "tooShort")}}: Возвращает <code>true</code>, если значение короче минимальной длины, указанной в атрибуте {{htmlattrxref("minlength", "input")}}, и <code>false</code> если оно длинее или равно ей. Если true, элемент соответствует CSS-псевдоклассу {{cssxref(":invalid")}}.</li>
   <li>{{domxref("ValidityState.rangeOverflow", "rangeOverflow")}}: Возвращает <code>true</code>, если значение больше указанного в атрибуте {{htmlattrxref("max", "input")}} максимума, и <code>false</code> если меньше или равно ему. Если true, элемент соответствует CSS-псевдоклассам {{cssxref(":invalid")}} и {{cssxref(":out-of-range")}}</li>
   <li>{{domxref("ValidityState.rangeUnderflow", "rangeUnderflow")}}: Возвращает <code>true</code>, если значение меньше указанного в атрибуте {{htmlattrxref("min", "input")}}, и <code>false</code> если больше или равно ему. Если true, элемент соответствует CSS-псевдоклассу {{cssxref(":invalid")}} и {{cssxref(":out-of-range")}}.</li>
   <li>{{domxref("ValidityState.typeMismatch", "typeMismatch")}}: Возвращает <code>true</code>, если значение не соответствует требуемому синтаксису (когда для {{htmlattrxref("type", "input")}} задано значение <code>email</code> или <code>url</code>), и <code>false</code> если синтаксис корректный. Если <code>true</code>, элемент соответствует CSS-псевдоклассу {{cssxref(":invalid")}}.</li>
   <li><code>valid</code>: Возвращает <code>true</code>, если элемент соответствует всем ограничениям валидации — следовательно, считается валидным, и <code>false</code> если не соответствует какому-то ограничению. Если true, элемент соответствует CSS-псевдоклассу {{cssxref(":valid")}}; иначе {{cssxref(":invalid")}}.</li>
   <li><code>valueMissing</code>: Возвращает <code>true</code>, если у элемента есть атрибут {{htmlattrxref("required", "input")}}, но не введено значенение, иначе возвращает <code>false</code>. Если true, элемент соответствует CSS-псевдоклассу {{cssxref(":invalid")}}.</li>
  </ul>
 </li>
 <li><code>willValidate</code>: Возвращает <code>true</code>, если элемент будет участвовать в валидации при отправке формы; иначе возвращает <code>false</code>.</li>
</ul>

<p id="Constraint_validation_API_methods">Также для перечисленных выше элементов Constraint Validation API  делает доступными следующие методы.</p>

<ul>
 <li><code>checkValidity()</code>: Возвращает <code>true</code>, если значение элемента проходит валидацию, иначе возвращает <code>false</code>. Если элемент не валиден, данный метод также запускает на нём событие <a href="/ru/docs/Web/API/HTMLInputElement/invalid_event"><code>invalid</code></a>.</li>
 <li><code>setCustomValidity(<em>message</em>)</code>: Позволяет добавить в элемент кастомное сообщение об ошибке; при этом элемент будет считаться не валидным и отобразится указанная ошибка. Это позволяет использовать JavaScript-код, чтобы представить ошибку валидации иначе, чем это предусмотрено стандартными средствами валидации HTML5. При сообщении об ошибке данное кастомное сообщение показывается пользователю.</li>
</ul>

<h4 id="Implementing_a_customized_error_message">Реализация кастомного сообщения об ошибке</h4>

<p>Как вы видели в примерах HTML5-валидации выше, каждый раз, когда пользователь пытается отправить не валидную форму, браузер отображает сообщение об ошибке. Способ отображения сообщения зависит от браузера.</p>

<p>У этих автоматических сообщений есть два недостатка:</p>

<ul>
 <li>Не существует стандартного способа их стилизации с помощью CSS.</li>
 <li>Они зависят от локали браузера, из-за чего страница может быть на одном языке, а сообщение об ошибке — на другом, как показано на следующем скриншоте браузера Firefox.</li>
</ul>

<p><img alt="Пример сообщения об ошибке на англоязычной странице в браузере Firefox с настроенным французским языком" src="error-firefox-win7.png"></p>

<p>Настройка таких сообщений об ошибках является одной из наиболее распространённых причин использования <a href="/en-US/docs/Web/API/Constraint_validation" rel="external">Constraint Validation API</a>. Давайте рассмотрим простой пример, как это делается.</p>

<p>Начнём с простого HTML (Не стесняйтесь поместить это в пустой HTML-файл. Вы можете взять за основу свежую копию <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a>, если хотите):</p>

<pre class="brush: html">&lt;form&gt;
  &lt;label for="mail"&gt;I would like you to provide me with an e-mail address:&lt;/label&gt;
  &lt;input type="email" id="mail" name="mail"&gt;
  &lt;button&gt;Submit&lt;/button&gt;
&lt;/form&gt;</pre>

<p>Добавьте на страницу следующий JavaScript:</p>

<pre class="brush: js">const email = document.getElementById("mail");

email.addEventListener("input", function (event) {
  if (email.validity.typeMismatch) {
    email.setCustomValidity("I am expecting an e-mail address!");
  } else {
    email.setCustomValidity("");
  }
});</pre>

<p>Здесь мы сохраняем ссылку на поле email, а затем добавляем к нему слушатель события, который запускает код обработчика каждый раз, когда в поле меняется значение.</p>

<p>В коде обработчика мы проверяем, возвращает ли свойство поля email <code>validity.typeMismatch</code> значение <code>true</code>, что значит, что содержащееся значение не соответствует шаблону корректного email-адреса. Если возвращается <code>true</code>, мы вызываем метод {{domxref("HTMLInputElement.setCustomValidity()","setCustomValidity()")}} с кастомным сообщением. Это делает поле не валидным, поэтому попытка отправить форму приводит к ошибке и отображается кастомное сообщение об ошибке.</p>

<p>Если свойство <code>validity.typeMismatch</code> возвращает <code>false</code>, мы вызываем метод <code>setCustomValidity()</code> с пустой строкой. Это делает поле валидным, поэтому форма может быть успешно отправлена.</p>

<p>Попробовать пример можно ниже:</p>

<p>{{EmbedGHLiveSample("learning-area/html/forms/form-validation/custom-error-message.html", '100%', 80)}}</p>

<div class="notecard note">
<p><strong>Примечание:</strong>: Данный пример можно найти на GitHub по адресу <a href="https://mdn.github.io/learning-area/html/forms/form-validation/custom-error-message.html">custom-error-message.html</a> (отдельно можно найти <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/custom-error-message.html">исходный код</a>.)</p>
</div>

<h4 id="A_more_detailed_example">Более подробный пример</h4>

<p>Теперь, когда мы разобрали простой пример, давайте посмотрим, как можно использовать данный API для создания более сложной валидацию.</p>

<p>Во-первых, HTML. Опять же, не стесняйтесь писать его вместе с нами:</p>

<pre class="brush: html">&lt;form novalidate&gt;
  &lt;p&gt;
    &lt;label for="mail"&gt;
      &lt;span&gt;Please enter an email address:&lt;/span&gt;
      &lt;input type="email" id="mail" name="mail" required minlength="8"&gt;
      &lt;span class="error" aria-live="polite"&gt;&lt;/span&gt;
    &lt;/label&gt;
  &lt;/p&gt;
  &lt;button&gt;Submit&lt;/button&gt;
&lt;/form&gt;</pre>

<p>Эта простая форма использует атрибут <code><a href="/en-US/docs/Web/HTML/Attributes/novalidate">novalidate</a></code>, который отключает автоматическую валидацию браузером; это позволяет нашему скрипту взять управление валидацией на себя. Однако, это не отменяет поддержку Constraint Validation API или псевдоклассов, таких как {{cssxref(":valid")}} или ему подобных. Это значит, что хотя браузер автоматически и не проверяет валидность формы перед отправкой данных, вы можете сделать это самостоятельно и соответствующим образом стилизовать форму.</p>

<p>Объектом валидации является обязательный для заполнения <code><a href="/en-US/docs/Web/HTML/Element/input/email">&lt;input type="email"&gt;</a></code>, длина которого не должна быть меньше 8 символов. Давайте напишем код, проверяющий эти критерии, и покажем кастомное сообщение об ошибке в случае несоблюдения какого-то из них.</p>

<p>Мы хотим показывать сообщение об ошибке внутри элемента <code>&lt;span&gt;</code>. Данному элементу задан атрибут <a href="/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions"><code>aria-live</code></a>, чтобы гарантировать, что наше кастомное сообщение об ошибке будет доступно всем, включая пользователей скринридеров.</p>

<div class="notecard note">
<p><strong>Примечание</strong>: Ключевым моментом здесь является то, что добавление к форме атрибута <code>novalidate</code> отключает отображение встроенных сообщений об ошибке и позволяет вместо этого добавлять в DOM кастомные сообщения.</p>
</div>

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

<pre class="brush: css">body {
  font: 1em sans-serif;
  width: 200px;
  padding: 0;
  margin : 0 auto;
}

p * {
  display: block;
}

input[type=email]{
  -webkit-appearance: none;
  appearance: none;

  width: 100%;
  border: 1px solid #333;
  margin: 0;

  font-family: inherit;
  font-size: 90%;

  box-sizing: border-box;
}

/* Это стили для не валидных полей */
input:invalid{
  border-color: #900;
  background-color: #FDD;
}

input:focus:invalid {
  outline: none;
}

/* Это стили для кастомных сообщений об ошибке */
.error {
  width  : 100%;
  padding: 0;

  font-size: 80%;
  color: white;
  background-color: #900;
  border-radius: 0 0 5px 5px;

  box-sizing: border-box;
}

.error.active {
  padding: 0.3em;
}</pre>

<p>Теперь давайте рассмотрим JavaScript, который реализует кастомную валидацию.</p>

<pre class="brush: js">
// Существуют разные способы получить DOM-узел; здесь мы определяем саму форму и
// поле ввода email и элемент span, в который поместим сообщение об ошибке
const form  = document.getElementsByTagName('form')[0];

const email = document.getElementById('mail');
const emailError = document.querySelector('#mail + span.error');

email.addEventListener('input', function (event) {
  // Каждый раз, когда пользователь что-то вводит,
  // мы проверяем, являются ли поля формы валидными

  if (email.validity.valid) {
    // Если на момент валидации какое-то сообщение об ошибке уже отображается,
    // если поле валидно, удаляем сообщение
    emailError.textContent = ''; // Сбросить содержимое сообщения
    emailError.className = 'error'; // Сбросить визуальное состояние сообщения
  } else {
    // Если поле не валидно, показываем правильную ошибку
    showError();
  }
});

form.addEventListener('submit', function (event) {
  // Если поле email валдно, позволяем форме отправляться

  if(!email.validity.valid) {
    // Если поле email не валидно, отображаем соответствующее сообщение об ошибке
    showError();
    // Затем предотвращаем стандартное событие отправки формы
    event.preventDefault();
  }
});

function showError() {
  if(email.validity.valueMissing) {
    // Если поле пустое,
    // отображаем следующее сообщение об ошибке
    emailError.textContent = 'You need to enter an e-mail address.';
  } else if(email.validity.typeMismatch) {
    // Если поле содержит не email-адрес,
    // отображаем следующее сообщение об ошибке
    emailError.textContent = 'Entered value needs to be an e-mail address.';
  } else if(email.validity.tooShort) {
    // Если содержимое слишком короткое,
    // отображаем следующее сообщение об ошибке
    emailError.textContent = `Email should be at least ${ email.minLength } characters; you entered ${ email.value.length }.`;
  }

  // Задаём соответствующую стилизацию
  emailError.className = 'error active';
}</pre>

<p>Комментарии объясняют логику хорошо, но кратко:</p>

<ul>
 <li>При каждом изменении значения поля, мы производим его валидацию. Если данные валидны, удаляем ранее отображаемые сообщения об ошибках. Если данные не валдны, запускаем <code>showError()</code>, чтобы показать соответствующую ошибку.</li>
 <li>При каждой попытке отправить форму, мы снова производим валидацию. Если данные валидны, позволяем отправку формы. Если данные не валидны, запускам <code>showError()</code>, чтобы показать соответствующее сообщение об ошибке, а также предотвращаем отправку формы с помощью <code><a href="/ru/docs/Web/API/Event/preventDefault">preventDefault()</a></code>.</li>
 <li>Функция <code>showError()</code> использует различные свойства объекта <code>validity</code> поля ввода, чтобы определить тип ошибки и отобразить соответсвущее сообщение.</li>
</ul>

<p>Рабочий пример:</p>

<p>{{EmbedGHLiveSample("learning-area/html/forms/form-validation/detailed-custom-validation.html", '100%', 150)}}</p>

<div class="notecard note">
<p><strong>Примечание</strong>: Рабочий пример можно найти на GitHub по адресу <a href="https://mdn.github.io/learning-area/html/forms/form-validation/detailed-custom-validation.html">detailed-custom-validation.html</a> (отдельно можно найти <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/detailed-custom-validation.html">исходный код</a>.)</p>
</div>

<p>Constraint Validation API явяется мощным инструментом валидации форм, позволяющим получить контроль над пользовательским интерфейсом, существенно превосходящий возможности HTML и CSS.</p>

<div class="notecard note">
<p><strong>Примечание</strong>: Для получения дополнительной информации смотрите руководства <a href="/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation">Constraint validation guide</a> и <a href="/en-US/docs/Web/API/Constraint_validation">Constraint Validation API</a>.</p>
</div>

<h3 id="Validating_forms_without_a_built-in_API">Проверка форм без встроенного API</h3>

<p>В некоторых случаях, например, при необходимости поддержки устаревших браузеров или <a href="/ru/docs/Learn/Forms/How_to_build_custom_form_controls">кастомных элементов формы</a>, вы не сможете или не захотите использовать Constraint Validation API. Вы по-прежнему сможете использовать JavaScript для валидации форм, но для этого всё нужно будет писать самостоятельно.</p>

<p>Для создания своего валидатора формы, задайте себе несколько вопросов:</p>

<dl>
 <dt>Какую тип валидации я должен выполнить?</dt>
 <dd>Вам нужно определить, как данные будут валидироваться: с помощью строковых операций, преобразования типов, регулярных выражений и так далее. Решать вам.</dd>
 <dt>Что мне нужно делать, если форма не проходит валидацию?</dt>
 <dd>Это явно вопрос пользовательского интерфейса. Вы должны решить, как в этом случае будет себя вести форма. Будет ли она  в любом случае отправлять данные? Нужно ли выделять поля, содержащие ошибки? Нужно ли отображать сообщения об ошибках?</dd>
 <dt>Как я могу помочь пользователю исправить не валидные данные?</dt>
 <dd>Чтобы снизить степень разочарования пользователя, очень важно предоставить как можно больше полезной информации, чтобы помочь исправить данные, которые он ввёл неправильно. Нужно предложить правильные варианты, чтобы дать понять, какие данные вы ожидаете от него получить, а также сообщение, чётко описывающее ошибку. Если вы хотите подробнее ознакомиться с требованиями к пользовательскому интрефейсу при валидации форм, предлагаем прочитать следующие статьи:
 <ul>
  <li>SmashingMagazine: <a href="https://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/" rel="external">Form-Field Validation: The Errors-Only Approach</a></li>
  <li>SmashingMagazine: <a href="https://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/" rel="external">Web Form Validation: Best Practices and Tutorials</a></li>
  <li>WebFX: <a href="https://www.webfx.com/blog/web-design/10-tips-for-optimizing-web-form-submission-usability/" rel="external">10 Tips for Optimizing Web Form Submission Usability</a></li>
  <li>A List Apart: <a href="https://www.alistapart.com/articles/inline-validation-in-web-forms/" rel="external">Inline Validation in Web Forms</a></li>
 </ul>
 </dd>
</dl>

<h4 id="An_example_that_doesnt_use_the_constraint_validation_API">Пример без использования Constraint Validation API</h4>

<p>Чтобы проиллюстрировать это дальше приводится упрощённая версия предыдущего примера, которая работает с устаревшими браузерами.</p>

<p>HTML почти тот такой же; мы только удалили функционал валидации HTML5.</p>

<pre class="brush: html">&lt;form&gt;
  &lt;p&gt;
    &lt;label for="mail"&gt;
        &lt;span&gt;Please enter an email address:&lt;/span&gt;
        &lt;input type="text" id="mail" name="mail"&gt;
        &lt;span class="error" aria-live="polite"&gt;&lt;/span&gt;
    &lt;/label&gt;
  &lt;/p&gt;
  &lt;!-- Для некоторых устаревших браузеров элементу `button` нужно добавлять
       атрибут `type` с явно заданным значением `submit` --&gt;
  &lt;button type="submit"&gt;Submit&lt;/button&gt;
&lt;/form&gt;</pre>

<p>CSS также не требует особых изменений; мы только заменили CSS-псевдокласс {{cssxref(":invalid")}} на реальный класс и не использовали селектор по атрибутам, так как он не работает в Internet Explorer 6.</p>

<pre class="brush: css">body {
  font: 1em sans-serif;
  width: 200px;
  padding: 0;
  margin : 0 auto;
}

form {
  max-width: 200px;
}

p * {
  display: block;
}

input.mail {
  -webkit-appearance: none;

  width: 100%;
  border: 1px solid #333;
  margin: 0;

  font-family: inherit;
  font-size: 90%;

  box-sizing: border-box;
}

/* Стилизация не валидных полей */
input.invalid{
  border-color: #900;
  background-color: #FDD;
}

input:focus.invalid {
  outline: none;
}

/* Стилизация сообщений об ошибках */
.error {
  width  : 100%;
  padding: 0;

  font-size: 80%;
  color: white;
  background-color: #900;
  border-radius: 0 0 5px 5px;
  box-sizing: border-box;
}

.error.active {
  padding: 0.3em;
}</pre>

<p>Существенно изменился только JavaScript-код, который теперь должен выполнять гораздо больше работы.</p>

<pre class="brush: js">
// Устаревшие браузеры поддерживают несколько способов получения DOM-узла
const form  = document.getElementsByTagName('form')[0];
const email = document.getElementById('mail');

// Ниже приведён способ получения узла следующего родственного DOM-элемента
// Он опасен, потому что можно создать бесконечный цикл.
// В современных браузерах лучше использовать `element.nextElementSibling`
let error = email;
while ((error = error.nextSibling).nodeType != 1);

// Согласно спецификации HTML5
const emailRegExp = /^[a-zA-Z0-9.!#$%&amp;'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;

// Многие устаревшие браузеры не поддерживают метод `addEventListener`
// Есть простой способ заменить его; и далеко не единственный
function addEvent(element, event, callback) {
  let previousEventCallBack = element["on"+event];
  element["on"+event] = function (e) {
    const output = callback(e);

    // Колбэк, который возвращает `false`, останавливает цепочку колбэков
    // и прерывает выполнение колбэка события
    if (output === false) return false;

    if (typeof previousEventCallBack === 'function') {
      output = previousEventCallBack(e);
      if(output === false) return false;
    }
  }
};

// Теперь мы можем изменить наши критерии валидации
// Поскольку мы не полагаемся на CSS-псевдокласс, для поля email
// нужно явно задать валидный / не валидный класс
addEvent(window, "load", function () {
  // Проверка, является ли поле пустым (помните, оно не являтеся обязательным)
  // Если поле не пустое, проверяем содержимое на соответствует шаблону email
  const test = email.value.length === 0 || emailRegExp.test(email.value);

  email.className = test ? "valid" : "invalid";
});

// Здесь определяется поведение при вводе пользователем значения поля
addEvent(email, "input", function () {
  const test = email.value.length === 0 || emailRegExp.test(email.value);
  if (test) {
    email.className = "valid";
    error.textContent = "";
    error.className = "error";
  } else {
    email.className = "invalid";
  }
});

// Здесь определяется поведение при попытке отправить данные
addEvent(form, "submit", function () {
  const test = email.value.length === 0 || emailRegExp.test(email.value);

  if (!test) {
    email.className = "invalid";
    error.textContent = "I expect an e-mail, darling!";
    error.className = "error active";

    // Некоторые устаревшие браузеры не поддерживают метод event.preventDefault()
    return false;
  } else {
    email.className = "valid";
    error.textContent = "";
    error.className = "error";
  }
});</pre>

<p>Результат выглядит следующим образом:</p>

<p>{{EmbedLiveSample("An_example_that_doesnt_use_the_constraint_validation_API", "100%", 130)}}</p>

<p>Как вы можете видеть, сделать собственную валидацию не так уж и сложно. Сложность состоит лишь в том, чтобы сделать его кроссплатформенным и работающим с любой формой, которую можно создать. Для проверки формы доступно множество библиотек, например <a href="https://rickharrison.github.io/validate.js/" rel="external">Validate.js</a>.</p>

<h2 id="Test_your_skills!">Проверьте свои навыки!</h2>

<p>Вы дошли до конца этой статьи, но можете ли вы вспомнить самую важную информацию? Вы можете найти дополнительные тесты, чтобы убедиться, что вы сохранили эту информацию, прежде чем двигаться дальше — <a href="/en-US/docs/Learn/Forms/Test_your_skills:_Form_validation">Test your skills: Form validation</a>.</p>

<h2 id="Summary">Заключение</h2>

<p>Для проверки формы на стороне клиента иногда требуется JavaScript, если вы хотите настроить стилизацию и сообщения об ошибках, но это всегда требует от вас внимательного отношения к пользователю. Всегда помните о необходимости помогать пользователям исправлять данные, которые они вводят. Для этого обязательно нужно:</p>

<ul>
 <li>Отображать явные сообщения об ошибках.</li>
 <li>Снисходительно относиться к формату ввода.</li>
 <li>Указывать, где именно возникла ошибка. Особенно в больших формах.</li>
</ul>

<p>После того, как вы убедились, что форма заполнена правильно, ее можно отправлять. Дальше мы рассмотрим <a href="/ru/docs/Learn/Forms/Sending_and_retrieving_form_data">отправку данных формы</a>.</p>

<p>{{PreviousMenuNext("Learn/Forms/UI_pseudo-classes", "Learn/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}</p>

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

<ul>
 <li><a href="/ru/docs/Learn/Forms/Your_first_form">Ваша первая форма</a></li>
 <li><a href="/ru/docs/Learn/Forms/How_to_structure_a_web_form">Как структурировать веб-формы</a></li>
 <li><a href="/ru/docs/Learn/Forms/Basic_native_form_controls">Основные встроенные элементы формы</a></li>
 <li><a href="/en-US/docs/Learn/Forms/HTML5_input_types">Типы полей ввода в HTML5</a></li>
 <li><a href="/en-US/docs/Learn/Forms/Other_form_controls">Другие элементы формы</a></li>
 <li><a href="/ru/docs/Learn/Forms/Styling_web_forms">Стилизация веб-форм</a></li>
 <li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Продвинутая стилизация форм</a></li>
 <li><a href="/en-US/docs/Learn/Forms/UI_pseudo-classes">UI псевдоклассы</a></li>
 <li><a href="/ru/docs/Learn/Forms/Form_validation">Валидация форм на стороне клиента</a></li>
 <li><a href="/ru/docs/Learn/Forms/Sending_and_retrieving_form_data">Отправка данных формы</a></li>
</ul>

<h3 id="Advanced_Topics">Продвинутые темы</h3>

<ul>
 <li><a href="/ru/docs/Learn/Forms/How_to_build_custom_form_controls">Как создавать кастомные элементы формы</a></li>
 <li><a href="/ru/docs/Learn/Forms/Sending_forms_through_JavaScript">Отправка форм с помощью JavaScript</a></li>
 <li><a href="/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_controls">Таблица совместимости CSS-свойств для элементов формы</a></li>
</ul>