Тег label (от английского label, «надпись», «метка») создаёт надпись для поля формы. Клик по label переводит фокус в связанное поле или переключает его, а текст надписи становится названием поля для программ чтения с экрана. Связь задают атрибутом for и id поля либо вложением поля внутрь label, а закрывающий тег обязателен.
Надпись нужна полям из тегов input, textarea и других элементов внутри тега form. Связь с полем и доступность разобраны в уроке «label и его связь с полем».
<label for="email">Почта</label>
<input id="email" name="email" type="email">
В этой статье
- Тег label в HTML: что это и для чего нужен
- Атрибут for: явная связь надписи с полем
- Поле внутри label: неявная связь и control
- Что записывают внутри label: теги, ссылки и вложенный label
- Клик по label: фокус, переключение и отмена
- Label для флажков и переключателей: область клика
- Какие элементы связывает label
- Атрибуты тега label
- Тег label и JavaScript: control, htmlFor и labels
- CSS для label: :checked, :has() и область клика
- Доступность label: название поля и aria-label
- Вопросы про тег label: отправка данных и двойной click
- Частые ошибки с тегом label
Тег label в HTML: что это и для чего нужен
Надпись нужна, чтобы пользователь понимал, что вводить, и чтобы сама надпись работала как часть поля. Обычный текст рядом с полем ни с чем не связан: клик по нему ничего не делает, а программа чтения с экрана не знает, что он относится к полю. Тег label это исправляет. У флажка и переключателя кликабельным становится весь текст, а не маленький квадрат. По умолчанию тег строчный (display: inline), а курсор над ним обычная стрелка.
<input type="checkbox" id="agree" name="agree">
<label for="agree">Согласен с правилами</label>
Пример: текст и label рядом с флажком
Выберите запись и кликните по тексту: под результатом состояние флажка и число кликов.
Атрибут for: явная связь надписи с полем
Атрибут for хранит значение id поля, которое нужно связать. Надпись и поле можно записывать в разных местах страницы, но id на странице должен быть один: при повторе с надписью связывается первый из таких элементов. Связи нет, если элемента с таким id нет, если это div или другой элемент без ввода, или если поле скрытое (type="hidden"). В этих случаях проверка HTML сообщает об ошибке. Одному полю можно дать несколько надписей.
<label for="city">Город</label>
<input id="city" name="city">
Пример: for и id
Выберите запись и нажмите кнопку: под результатом связанное поле label.control и фокус.
Поле внутри label: неявная связь и control
Если поле записано внутри label, ни for, ни id не нужны: связанным становится первое подходящее поле внутри. Допустимо одно поле, два поля проверка HTML считает ошибкой. Если указать и for, и вложенное поле с другим id, побеждает for. Вложение удобно, когда флажок и текст оформляют одним блоком, а запись с for нужна, когда надпись и поле стоят в разных местах. Связанное поле в скрипте доступно как label.control.
<label>Город <input name="city"></label>
Пример: поле внутри label
Выберите запись и нажмите кнопку: под результатом связанное поле label.control и фокус.
Что записывают внутри label: теги, ссылки и вложенный label
Внутри label допустим текст и строчные теги: span, b, img, a. Заголовки, div и вложенный label проверка HTML считает ошибкой, а заголовок для надписи не нужен. Ссылка внутри допустима, но клик по ней открывает страницу и флажок не переключает, а клик по остальному тексту переключает. Если переключение важно, ссылку на правила записывают рядом с label, а не внутри.
<label for="agree">Согласен с <a href="/rules">правилами</a></label>
Пример: что записывают внутри label
Выберите запись и кликните по тексту и по ссылке: под результатом состояние флажка.
Клик по label: фокус, переключение и отмена
Клик по label браузер передаёт связанному полю. Текстовое поле и textarea получают фокус, список тоже получает фокус, но не раскрывается. Флажок переключается, переключатель выбирается, а у кнопки срабатывает её собственный click. Отключённое поле (disabled) на клик не реагирует. Передачу отменяет preventDefault() в обработчике click у самого label.
const label = document.querySelector("label");
label.addEventListener("click", (e) => {
e.preventDefault();
});
Пример: что происходит с полем при клике
Выберите поле и кликните по надписи: под результатом фокус, состояние и число событий click у поля.
Label для флажков и переключателей: область клика
Для флажка и переключателя label особенно важен: сам элемент маленький, и попасть в него пальцем трудно. С надписью кликабельным становится весь текст, а размер области задают отступы: padding у label с display: block или inline-block увеличивает цель клика. У каждого переключателя в группе своя надпись, а общее название группы задают через fieldset и legend.
<label><input type="radio" name="plan" value="free"> Бесплатно</label>
<label><input type="radio" name="plan" value="pro"> Платно</label>
Пример: область клика у флажка и переключателя
Выберите запись и кликните по тексту: под результатом состояние полей и число кликов не по полю.
Какие элементы связывает label
Связать с надписью можно только помечаемые элементы: input (кроме type="hidden"), select, textarea, button, meter, output и progress. У остальных, например у div, связи нет. Клик по надписи переносит фокус только на то, что умеет его получать, а meter, output и progress получают название, но фокус не принимают.
<label for="vol">Громкость</label>
<meter id="vol" value="0.6"></meter>
Пример: какие элементы связывает label
Выберите элемент и нажмите кнопку: под результатом label.control и фокус.
Атрибуты тега label
У label один собственный атрибут, for, и глобальные атрибуты. Несуществующие отмечены отдельно: часть из них знакома по полям формы, но у label они не работают, а проверка HTML сообщает об ошибке.
| Атрибут | Статус | Что делает | Пример записи |
|---|---|---|---|
for | актуален | id поля, с которым связана надпись | <label for="email"> |
class | глобальный | Класс для оформления | <label class="field"> |
id | глобальный | Идентификатор самой надписи, например для aria-labelledby | <label id="lbl"> |
style | глобальный | Встроенные стили | <label style="color: red"> |
title | глобальный | Всплывающая подсказка | <label title="Обязательно"> |
form | не существует | Форму указывают самому полю, а не надписи | <label form="order"> |
name | не существует | Надпись не отправляется, атрибут name нужен полю | <label name="email"> |
value | не существует | У надписи нет значения | <label value="Почта"> |
type | не существует | Тип задают полю | <label type="email"> |
placeholder | не существует | Подсказку задают полю | <label placeholder="Почта"> |
Тег label и JavaScript: control, htmlFor и labels
Свойство control возвращает связанное поле или null, а htmlFor читает и меняет атрибут for. В обратную сторону у поля есть labels: список всех его надписей по порядку, у скрытого поля он равен null. Новую надпись создают через createElement("label") и htmlFor, и она сразу попадает в labels.
const label = document.querySelector("label");
console.log(label.control);
console.log(label.htmlFor);
const input = document.querySelector("input");
console.log(input.labels.length);
Пример: control, htmlFor и labels
Выберите запись: под результатом ответ скрипта.
CSS для label: :checked, :has() и область клика
Своих стилей у надписи почти нет. Состояние флажка подсвечивают соседним селектором input:checked + label, когда надпись записана после поля, или селектором label:has(input:checked), когда флажок внутри. Курсор pointer и отступы показывают, что надпись кликабельна. Двойной клик по тексту выделяет его. Выделение отключает user-select: none.
label {
cursor: pointer;
padding: 8px 12px;
}
input:checked + label {
color: #c0392b;
}
Пример: подсветка и область клика
Выберите стиль, кликните по надписи и дважды по тексту: под результатом курсор, display и состояние флажка.
Доступность label: название поля и aria-label
Текст label становится названием поля для программ чтения с экрана. Приоритет такой: aria-labelledby главнее aria-label, а он главнее label. Если ничего нет, название берётся из title, а затем из placeholder. Если надписей у поля две, браузер соединяет их тексты. Надпись, скрытая только визуально, остаётся названием поля. Так оформляют поле поиска, где вместо текста стоит значок.
<label for="q" class="vh">Поиск</label>
<input id="q" type="search" name="q">
Пример: откуда берётся название поля
Выберите запись: под результатом название поля для программы чтения с экрана.
Вопросы про тег label: отправка данных и двойной click
Про label часто спрашивают, что уходит на сервер и почему обработчик click срабатывает дважды.
Отправляет ли label данные на сервер?
Нет. Сам label в отправке не участвует: уходят пары из name и значения полей. Поле без name не отправляется, даже если связано с надписью, а поле с name уходит и без надписи. Текст надписи в данные не попадает.
<form action="/send" method="post">
<label for="email">Почта</label>
<input id="email" name="email">
</form>
Пример: что уходит при отправке формы
Выберите запись и нажмите «Отправить»: под результатом данные формы.
Почему обработчик click срабатывает дважды при клике по label?
Браузер передаёт клик по надписи полю отдельным событием click, и оно тоже всплывает к родителю. Получается два события: у первого целью служит label, у второго поле. Решений три: слушать change, пропускать события, у которых event.target не поле, или повесить обработчик на само поле.
wrap.addEventListener("click", (e) => {
if (e.target !== input) return;
count++;
});
Пример: три способа посчитать клики
Выберите способ и кликните по тексту: под результатом счётчик и цели событий.
Частые ошибки с тегом label
Ошибки с надписью в основном про связь с полем и допустимое содержимое.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
Обычный текст рядом с полем вместо label | Клик по тексту ничего не делает, программа чтения не знает название поля | Обернуть текст в label и связать с полем |
for не совпадает с id | Связи нет, клик по надписи не действует | Сверить значения, а id на странице сделать уникальным |
for указывает на div или на input type="hidden" | Связи нет, проверка HTML сообщает об ошибке | Связывать надпись с полем ввода |
Два поля внутри одного label | Связанным считается только первое, проверка HTML сообщает об ошибке | Дать каждому полю свою надпись |
Заголовок, div или другой label внутри label | Запись недопустима, проверка HTML сообщает об ошибке | Оформлять текст через span и CSS |
Ссылка внутри label | Клик по ссылке открывает страницу и не переключает флажок | Записать ссылку рядом с надписью, если нужно переключение |
Вместо надписи только placeholder | Подсказка пропадает при вводе, название поля ненадёжное | Добавить label |
aria-label с другим текстом поверх label | Программа чтения определяет название по aria-label, а на экране виден другой текст | Использовать один источник названия |
Нет name у поля | Поле связано с надписью, но в данные формы не попадает | Добавить name |