Тег form (от английского form, «форма») объединяет поля и кнопки в одну форму, которую браузер отправляет целиком. Это парный тег: закрывающий </form> обязателен. Без form поля выводятся, но отправлять браузеру нечего. Куда и как уйдут данные, определяют атрибуты action, method и enctype.
Сами поля (input, textarea, select) и кнопка button разобраны на отдельных страницах группы. Здесь только форма как контейнер: адрес и способ отправки, что допустимо внутри, как ведёт себя вложенность, как работает отправка по Enter и что из формы берут скрипт и CSS. Форму поиска по сайту дополнительно оборачивают в тег search.
<form action="/send" method="post">
<input name="name" value="Кот">
<button>Отправить</button>
</form>
В этой статье
- Тег form в HTML: что это, зачем нужен и парный ли он
- Атрибут action тега form: куда уходят данные
- Атрибут method тега form: get, post и dialog
- Атрибут enctype тега form: когда нужен multipart
- Остальные атрибуты тега form: target, novalidate, autocomplete, name
- Теги внутри form: что можно записать и что попадёт в отправку
- Тег form внутри form: что делает браузер
- Атрибут form у поля: поле снаружи тега form
- Тег form: отправка кнопкой и клавишей Enter
- Тег form и JavaScript: submit, requestSubmit и FormData
- CSS для тега form: умолчания, :valid и :invalid
- Доступное название у тега form: когда форма становится ориентиром
- Вопросы про тег form: несколько форм и закрывающий тег
- Частые ошибки с тегом form
Тег form в HTML: что это, зачем нужен и парный ли он
Тег form блочный: display: block и нулевые внешние отступы. Он собирает значения всех полей внутри себя, и по нажатию кнопки браузер отправляет их на сервер. Поле вне формы выводится так же, но в отправку не входит: у него нет формы, к которой он относится. Закрывающий тег записывают всегда, а что случится без него, показано в вопросах в конце страницы.
<form>
<input name="name" value="Кот">
<button>Отправить</button>
</form>
<input name="age" value="3">
Пример: поля с form и без него
Выберите запись: вверху код, под результатом сколько полей в форме и что уйдёт. Кнопки в примере нажимаются.
Атрибут action тега form: куда уходят данные
Атрибут action задаёт адрес, на который отправляют данные. Адрес бывает полным (https://example.com/send), от корня сайта (/send) или относительным (send): относительный адрес считают от адреса страницы или от значения в теге base. Если action не записан, данные уходят на адрес самой страницы. Это удобно, когда страница сама обрабатывает свою форму. Пустой action="" работает так же, но валидатор его не принимает, поэтому атрибут лучше не записывать совсем.
<form action="/send">
<input name="q">
</form>
Пример: куда уйдут данные при разных action
Выберите запись: вверху код, под результатом готовый адрес отправки. Адрес страницы в примере условный.
Атрибут method тега form: get, post и dialog
Атрибут method принимает три значения. Значение get дописывает данные к адресу после знака вопроса, поэтому результат можно сохранить закладкой или отправить ссылкой. Значение post передаёт данные в теле запроса, адрес остаётся чистым. Значение dialog ничего не отправляет на сервер: форма внутри dialog закрывает его. Регистр не важен, а неизвестное значение и отсутствие атрибута браузер читает как get.
<form action="/search" method="get">
<input name="q">
</form>
Пример: get, post и dialog
Выберите значение и измените текст в поле: под результатом куда и как уходят данные.
Атрибут enctype тега form: когда нужен multipart
Атрибут enctype определяет, как кодируются данные при method="post". По умолчанию действует application/x-www-form-urlencoded: пары название=значение через знак &, кириллица и спецсимволы заменяются кодами. Значение multipart/form-data обязательно, если в форме есть выбор файла: только оно передаёт содержимое файла, а не его название. Значение text/plain записывает пары строками как есть и годится для отладки. При get атрибут не действует.
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="doc">
<button>Загрузить</button>
</form>
Пример: что уходит при разных enctype
Выберите значение, измените текст или выберите файл: под результатом тело, которое собрал бы браузер, граница условная.
Остальные атрибуты тега form: target, novalidate, autocomplete, name
Остальные атрибуты формы меняют проверку полей, место для ответа сервера и подсказки браузера. novalidate отключает проверку required, pattern и type при отправке. name нужен скриптам: форма доступна как document.forms.order. autocomplete="off" просит браузер не подставлять сохранённые значения, а target="_blank" открывает ответ в новой вкладке.
<form action="/send" novalidate name="order" autocomplete="off" target="_blank">
<input name="q" required>
<button>Отправить</button>
</form>
Пример: novalidate, name, autocomplete и target
Выберите атрибут и нажмите Отправить при пустом поле: под результатом что сделал браузер.
Все атрибуты формы собраны в таблице, устаревший accept отмечен отдельно.
| Атрибут | Статус | Что делает | Пример записи |
|---|---|---|---|
action | актуален | Адрес, на который уходят данные. Без атрибута данные уходят на адрес страницы | <form action="/send"> |
method | актуален | Способ отправки: get, post или dialog | <form method="post"> |
enctype | актуален | Кодирование данных при post. Для файлов нужен multipart/form-data | <form enctype="multipart/form-data"> |
target | актуален | Где показать ответ сервера: _self, _blank, _parent, _top или название окна | <form target="_blank"> |
novalidate | актуален | Отключает проверку полей при отправке | <form novalidate> |
autocomplete | актуален | Включает или отключает сохранённые значения для полей формы. Поле может задать своё значение | <form autocomplete="off"> |
name | актуален | Название формы для скриптов. Доступного названия для программ чтения с экрана не задаёт | <form name="order"> |
accept-charset | актуален | Кодировки для отправки. По умолчанию берётся кодировка страницы, поэтому атрибут почти не нужен | <form accept-charset="utf-8"> |
rel | актуален | Типы связей, как у ссылок: noopener, noreferrer и другие | <form target="_blank" rel="noopener"> |
accept | устарел | Раньше перечислял типы файлов формы. Сейчас accept записывают у input с типом file | <form accept="image/*"> |
Теги внутри form: что можно записать и что попадёт в отправку
Внутри form допустим любой контент, который допустим в теге div: поля, кнопки, надписи label, fieldset, заголовки, таблицы и абзацы вроде тег p. Исключение одно: другой form. В список form.elements попадают только управляющие элементы: button, fieldset, input, object, output, select и textarea, кроме input type="image". Надписи label, картинки и ссылки в него не входят.
<form>
<label>Имя <input name="name"></label>
<input type="email" name="mail">
</form>
Пример: что попадает в form.elements
Выберите запись: вверху код, под результатом какие элементы вошли в список формы.
Тег form внутри form: что делает браузер
Форма внутри формы в разметке не получится. При разборе браузер отбрасывает внутренний открывающий тег form, а первый закрывающий </form> закрывает внешнюю форму, даже если стоит внутри блока. Поля внутренней формы остаются во внешней, а всё, что записано после закрывающего тега, оказывается вне формы. Скриптом вложенную форму создать можно, но у поля владельцем станет ближайшая форма, а внешняя останется без полей. Если нужны две отправки с разными адресами, берут две формы рядом или кнопки с атрибутом formaction.
<form id="a">
<input name="x">
<form id="b">
<input name="y">
</form>
<input name="z">
</form>
Пример: как разбирается вложенная форма
Выберите способ записи: под результатом какие формы получились и какие поля в каких.
Атрибут form у поля: поле снаружи тега form
Поле или кнопка вне тега form попадает в форму, если у неё записан атрибут form со значением id нужной формы. Так отправляют кнопку из шапки страницы, поле из боковой колонки или кнопку «Сохранить» в закреплённой панели. Значение указывает на id одной формы, несуществующий id поле ни к чему не привязывает. Атрибут есть у button, fieldset, input, object, output, select и textarea.
<form id="f1">
<input name="a" value="1">
</form>
<input name="x" value="9" form="f1">
Пример: поле снаружи формы с атрибутом form
Выберите запись: под результатом данные каждой формы и владелец поля x.
Тег form: отправка кнопкой и клавишей Enter
Форму отправляет кнопка отправки: button без type по умолчанию именно такая. Но форму отправляет и клавиша Enter в поле. Это неявная отправка, и у неё свои условия. Если в форме есть кнопка отправки, Enter нажимает её, а отключённая кнопка отправку блокирует. Если кнопки нет, форма отправится только при одном поле ввода: флажки, списки и textarea не в счёт. В textarea клавиша переносит строку. Из скрипта форму отправляют методом requestSubmit(), он описан в разделе про JavaScript.
<form>
<input name="a">
<input name="b">
<button>Отправить</button>
</form>
Пример: когда Enter отправляет форму
Выберите запись, нажмите в поле клавишу Enter (на телефоне кнопку ввода): под результатом что ожидается и сколько отправок сработало.
Тег form и JavaScript: submit, requestSubmit и FormData
Событие submit срабатывает на форме, а не на кнопке: так обрабатываются и клик, и Enter. В обработчике вызывают preventDefault(), если страница не должна перезагружаться. Данные собирает new FormData(form), а доступ к полям даёт form.elements. Метод requestSubmit() запускает отправку как пользователь: с проверкой полей и событием submit. Метод submit() отправляет форму сразу, без проверки и без события. Если нужно знать, какая кнопка нажата, смотрят свойство submitter у события.
form.addEventListener('submit', e => {
e.preventDefault();
const data = new FormData(form);
console.log(e.submitter, [...data]);
});
form.requestSubmit();
Пример: submit, requestSubmit и FormData
Нажмите на метод: под результатом сработало ли событие, прошла ли проверка и какая кнопка отправила форму.
CSS для тега form: умолчания, :valid и :invalid
У form почти нет собственных стилей: блочный элемент без внешних отступов. Этим он отличается от абзаца, у которого отступы по 1em. Состояние проверки доступно прямо у формы через псевдоклассы :valid и :invalid: форма считается :invalid, пока хоть одно её поле не проходит проверку. Через :has() можно показать сообщение, когда в форме есть поле с ошибкой. Оформление записывают в CSS по классу формы, а не по тегу, если на странице несколько разных форм.
form:invalid {
border: 2px solid #d33;
}
form:valid {
border: 2px solid #2a8;
}
Пример: умолчания и :invalid у form
Выберите правило и введите возраст: под результатом вычисленные значения и состояние проверки.
Доступное название у тега form: когда форма становится ориентиром
Программа чтения с экрана объявляет форму ориентиром form только тогда, когда у неё есть доступное название: aria-label, aria-labelledby или title. Без названия форма остаётся обычным блоком. Атрибут name названия не задаёт, он нужен скриптам. Ориентир полезен там, где на странице несколько форм: на каждую можно перейти списком ориентиров. Остальные ориентиры страницы описаны на странице про тег aside.
<form aria-label="Поиск по сайту">
<input type="search" aria-label="Запрос">
</form>
Пример: когда форма становится ориентиром
Выберите запись: вверху код, под результатом станет ли форма ориентиром.
Вопросы про тег form: несколько форм и закрывающий тег
Форм на странице бывает несколько, а закрывающий тег иногда пропускают: сколько форм допустимо и обязателен ли закрывающий тег.
Сколько форм может быть на одной странице?
Сколько нужно: ограничения нет. Каждая форма отправляется отдельно, а данные соседних форм с ней не уходят. Например, поиск, вход и подписка на одной странице записывают тремя отдельными формами.
<form id="search">
<input name="q">
<button>Найти</button>
</form>
<form id="login">
<input name="email">
<button>Войти</button>
</form>
Пример: три формы на одной странице
Нажмите кнопку любой формы или Enter в её поле: под результатом какая форма отправилась.
Обязателен ли закрывающий тег form?
Да. Без него форма продолжается до конца родительского блока, а поле, записанное после закрытия блока, всё равно остаётся в форме. Из-за этого в отправку попадают лишние поля, поэтому закрывающий тег записывают сразу после последнего поля и кнопки.
<div>
<form>
<input name="a">
</div>
<input name="b">
Пример: что случается без закрывающего тега
Выберите запись: под результатом какие поля вошли в форму. Зелёная рамка у поля из формы, красная у поля вне формы.
Частые ошибки с тегом form
Типичные ошибки с формой: от забытого закрывающего тега до отправки скриптом без проверки.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
Закрывающий </form> не записан | Следующие поля попадают в форму, даже после закрытого блока | Закрывать форму сразу после последнего поля и кнопки |
Один form записан внутри другого | Внутренний открывающий тег отбрасывается, поля обеих форм уходят вместе | Записать формы рядом, для двух адресов задать кнопкам formaction |
У поля нет name: <input value="кот"> | Поле выводится, но в отправку не попадает | Записать <input name="q" value="кот"> |
action="send" на странице /blog/post.html | Данные уходят на /blog/send, а не на /send | Записать адрес от корня: action="/send" |
Для выбора файла не задан enctype="multipart/form-data" | Уходит только название файла, а не его содержимое | Записать method="post" и enctype="multipart/form-data" |
Кнопка отправки записана вне form | Нажатие ничего не отправляет | Перенести кнопку в форму или записать form="id" |
Скрипт вызывает form.submit() и ждёт проверки полей | Проверка required и событие submit пропускаются | Вызывать form.requestSubmit() |
Форма поиска отправляется через method="post" | Результаты нельзя сохранить закладкой или отправить ссылкой: данных нет в адресе | Записать method="get" |
| На странице несколько форм, и ни у одной нет названия | Программа чтения с экрана не выделяет формы ориентирами | Записать aria-label или aria-labelledby |