Верстка форм
-
Не используйте для разметки групп инпутов
div
иh1-h6
#- Почему? #
-
Для разметки групп полей есть более подходящие теги:
fieldset
иlegend
. Они не только внесут разнообразие в код, но также сделают вашу форму более доступной. - А как надо? #
-
С чистыми
fieldset
иlegend
могут возникать затруднения при стилизации и позиционировании контента, но это легко решается дополнительными обёртками.Например, так как
fieldset
используется для групп полей, а у каждого поля есть лейбл, каждой пареinput
+label
обычно требуется обёртка, и здесь можно удобно использовать ненумерованные списки (ul
). После этого можно всё позиционирование делать для списка и его элементов, и с раскладкой больше не будет никаких проблем. Чтобы вместе с инпутом не читалась информация об элементах списка, его нужно скрыть от скринридеров, задавrole="none"
.legend
ведёт себя своеобразно, но его можно вырвать со своего места с помощьюfloat: left
, а для позиционирования текста внутриlegend
завернуть текст в спаны.-
Плохо
<div> <h3>Контакты</h3> <label for="name">Имя</label> <input type="text" name="name" id="name"> <label for="surname">Фамилия</label> <input type="text" name="surname" id="surname"> </div>
-
Хорошо
<fieldset> <legend>Контакты</legend> <ul role="none"> <li> <label for="name">Имя</label> <input type="text" name="name" id="name"> </li> <li> <label for="surname">Фамилия</label> <input type="text" name="surname" id="surname"> </li> </ul> </fieldset>
-
-
Не используйте
legend
вместоlabel
#- Почему? #
-
В некоторых макетах можно увидеть, что название для
textarea
выглядит какlegend
, и возникает соблазн поместитьtextarea
вfieldset
, а название поля поместить вlegend
.Это будет не самым правильными решением, потому что у всех инпутов должны быть лейблы. Если добавить скрытый лейбл, его содержимое будет дублировать уже имеющийся
legend
, и всё это вместе будет выглядеть довольно странно. - Как это увидеть? #
-
Посмотрите на форму без стилей:
- А как надо? #
-
Для одиночного текстового поля не нужны
fieldset
иlegend
, они для групп полей. Если такому полю требуется обёртка, можно использоватьdiv
. Название поля нужно поместить вlabel
.Если стилизация
legend
не привязана к тегу, вы без проблем можете использовать эти же стили (а лучше класс) для стилизации лейбла.-
Плохо
<fieldset class="form-group"> <legend class="form-group__title"> Опишите привычки кота </legend> <label class="form-group__label visually-hidden" for="cat-habits"> Опишите привычки кота </label> <textarea class="form-group__textarea" id="cat-habits" placeholder="Введите текст" ></textarea> </fieldset>
-
Хорошо
<div class="form-group"> <label class="form-group__title" for="cat-habits"> Опишите привычки кота </label> <textarea class="form-group__textarea" id="cat-habits" placeholder="Введите текст" ></textarea> </div>
Теперь ничего не дублируется:
-
-
Не используйте
display: none
для скрытия инпутов #-
Инпуты, спрятанные таким образом, становятся полностью недоступны для скринридеров и навигации с клавиатуры
-
Установите фокус в первое поле и перемещаясь по форме с помощью
Tab
и стрелок попробуйте выбрать цвет кота:Ничего не получится, с клавиатуры выбор цвета недоступен.
-
Для скрытия инпутов используйте класс
.visuallyhidden
:.visuallyhidden { position: absolute; width: 1px; height: 1px; margin: -1px; border: 0; padding: 0; white-space: nowrap; clip-path: inset(100%); clip: rect(0 0 0 0); overflow: hidden; }
Это скроет инпут для обычных пользователей, но оставит его доступным для скринридеров. Почитать подробнее можно тут.
Попробуйте теперь с помощью
Tab
и стрелок выбрать цвет кота (чтобы выбрать цвет нажмите пробел):Всё работает.
-
Итого
- Не используйте для разметки групп инпутов
div
иh1-h6
, есть более подходящие теги:fieldset
иlegend
. - Не используйте
legend
вместоlabel
для одиночного поля, ему не нужныfieldset
иlegend
, достаточноdiv
иlabel
. - Не используйте
display: none
для скрытия инпутов, они становятся недоступны для скринридеров и навигации с клавиатуры. Скрывайте с помощью.visuallyhidden