Формы: как сайт спрашивает
Поля всех типов, подписи через label, встроенная проверка, группировка через fieldset — и почему placeholder не заменяет подпись.
Что ты научишься делать
- Соберёшь форму записи, которой удобно пользоваться и мышью, и с клавиатуры
- Свяжешь подпись с полем так, чтобы по подписи можно было кликнуть
- Включишь проверку данных браузером, без единой строчки JavaScript
#Форма — это конверт
Всё, что человек вводит на сайте, живёт внутри тега form. Он собирает данные полей и отправляет их по адресу из атрибута action.
Пока сервера у нас нет, но привыкать к правильной структуре стоит сразу: поля вне формы не отправятся никуда и не будут работать с клавишей Enter.
<form action="/booking" method="post"> <!-- поля --> <button type="submit">Записаться</button></form>#label: подпись, по которой можно кликнуть
label — не просто текст рядом с полем. Он связан с полем, и связь даёт две вещи: клик по подписи ставит курсор в поле (важно для маленьких флажков), а голосовая программа произносит подпись, когда фокус попадает в поле.
Связать можно двумя способами.
<!-- через id: подпись и поле связаны по имени --><label for="name">Как тебя зовут</label><input type="text" id="name" name="name"><!-- через вложенность: поле внутри подписи --><label> Как тебя зовут <input type="text" name="name"></label>#Типы полей
Тег input один, а поведение задаёт атрибут type. Правильный тип — это не только внешний вид: на телефоне под каждый тип открывается своя клавиатура, а браузер сам проверяет формат.
| type | Что даёт |
|---|---|
text | Обычная строка |
email | Проверка формата + клавиатура с собакой на телефоне |
tel | Цифровая клавиатура. Формат не проверяется — телефоны бывают разные |
password | Символы скрыты точками |
number | Только числа, атрибуты min, max, step |
date, time | Календарь и часы браузера |
checkbox | Независимый флажок |
radio | Выбор одного из группы. Объединяются одинаковым name |
range | Ползунок |
color | Палитра |
file | Выбор файла |
#Не только input
select — выпадающий список. Внутри — option. Удобен, когда вариантов больше пяти-шести.
textarea — многострочное поле. У него нет атрибута value: текст пишется между тегами.
button — кнопка. Тип submit отправляет форму, button — ничего не делает сам по себе.
<label for="drink">Напиток</label><select id="drink" name="drink"> <option value="">— выбери —</option> <option value="latte">Латте</option> <option value="raf">Раф</option></select><label for="note">Пожелания</label><textarea id="note" name="note" rows="4"></textarea>#Встроенная проверка
Браузер умеет проверять данные сам — бесплатно и на всех языках.
required— поле обязательное.minlength,maxlength— длина текста.min,max— границы числа или даты.pattern— свой шаблон через регулярное выражение.
К pattern обязательно добавляй title: браузер покажет его текстом ошибки. Без него человек увидит только «Данные не соответствуют формату» и не поймёт, что не так.
#Группировка: fieldset и legend
Когда несколько полей относятся к одному вопросу — особенно переключатели — их оборачивают в fieldset, а общий вопрос пишут в legend.
Без этого голосовая программа прочитает «S», «M», «L» и не скажет, что это размер стакана.
<fieldset> <legend>Размер стакана</legend> <label><input type="radio" name="size" value="s" checked> Маленький</label> <label><input type="radio" name="size" value="m"> Средний</label> <label><input type="radio" name="size" value="l"> Большой</label></fieldset>Где спотыкаются почти все
Подпись сделана обычным текстом или placeholder’ом
Почему Клик по такой подписи не ставит курсор в поле, а голосовая программа не связывает её с полем. Placeholder вдобавок исчезает при вводе.
Как надо Каждому полю — label с for, совпадающим с id поля.
Все поля сделаны type="text"
Почему На телефоне везде открывается буквенная клавиатура, а браузер ничего не проверяет: почта без собаки проходит.
Как надо Ставь честный тип: email, tel, number, date.
У полей нет атрибута name
Почему Данные без имени не отправляются на сервер вообще. Форма выглядит рабочей, но приходит пустой.
Как надо Каждому полю, которое должно отправиться, — свой name.
Кнопка сделана из div
Почему До div нельзя добраться клавишей Tab и нажать пробелом. Форма становится недоступной для клавиатуры.
Как надо Кнопка — это <button>. Она уже умеет всё: фокус, Enter, пробел, объявление роли.
- Форма form
- Блок, который собирает введённые данные и отправляет их по адресу из
action. - Подпись поля label
- Текст, связанный с полем через
forиidили вложенностью. - Подсказка в поле placeholder
- Пример ввода внутри поля. Исчезает при печати и не заменяет подпись.
- Встроенная валидация constraint validation
- Проверка данных силами браузера:
required,pattern,min,max. - Группа полей fieldset / legend
- Объединение полей одного вопроса с общим названием.
Проверь себя
Связь подписи с полем — это и удобство (большая область попадания), и доступность.
Только совпадающий <code>name</code>. Разные имена — и все переключатели включаются независимо.
Имя — это ключ, под которым значение уходит на сервер. Нет имени — нет данных, и никакой ошибки при этом не будет.
Браузер вставляет <code>title</code> в текст ошибки. Без него человек видит только «Данные не соответствуют формату».
Верных вариантов несколько.
Группировка нужна там, где у нескольких полей общий вопрос. Одиночному полю хватает своего <code>label</code>.
Задание
Форма записи
Собери форму: три поля — имя (text, обязательное), почта (email, обязательное) и дата (date). У каждого поля должна быть подпись label, связанная через for и id, и атрибут name. В конце — кнопка button с типом submit.
Подсказка 1
Скопируй блок <p> с полем имени и поменяй в копии type, id, name и текст подписи. Значение for должно совпадать с id.
Подсказка 2
Кнопка пишется так: <button type="submit">Записаться</button> — прямо перед закрывающим </form>.
Показать решение
<form> <p> <label for="name">Имя</label> <input type="text" id="name" name="name" required> </p> <p> <label for="mail">Почта</label> <input type="email" id="mail" name="mail" required placeholder="hi@polka.ru"> </p> <p> <label for="day">Удобная дата</label> <input type="date" id="day" name="day"> </p> <button type="submit">Записаться</button></form>label { display: block; font-weight: 600; margin-bottom: 4px; }input { padding: 8px; font: inherit; }p { margin: 0 0 12px; }