Должен ли я поместить элементы ввода внутри элемента метки?

606

Есть ли лучшая практика в отношении вложенности labelи inputHTML элементов?

классический способ:

<label for="myinput">My Text</label>
<input type="text" id="myinput" />

или

<label for="myinput">My Text
   <input type="text" id="myinput" />
</label>
jpsimard-Никс
источник
107
Один из больших плюсов размещения <input />внутри <label>, это то, что вы можете опустить forи id: <label>My text <input /></label>в вашем примере. Так намного лучше!
Знаркус
16
Хотя я согласен с тем, что inputсемантически не принадлежит внутри a label, сегодня я заметил, что разработчики Bootstrap не согласны со мной . Некоторые элементы, такие как встроенные флажки, оформлены по-разному в зависимости от того, inputнаходится ли он внутри или снаружи.
Blazemonger
6
Кстати, это было действительно плохой идеей для создания, так <label for="id">как у меня есть несколько форм на странице, и я не могу использовать idатрибут для многих виджетов, не попав в unique id per pageловушку. Единственный приемлемый способ получить доступ к виджету - form + widget_name.
MaxZoom
5
@MaxZoom, если на вашей странице так много разных форм с одинаковыми именами полей, что у вас возникают проблемы с созданием уникальных идентификаторов, возможно, вы захотите немного пересмотреть дизайн страницы, ИМХО; очевидно, я не знаю твоего положения, но мне это просто плохо пахнет
Кен Беллоуз
5
@kenbellows Идея дизайнера / бизнеса (не моя) - разместить две формы поиска на одной странице. Лучшие практики взаимодействия с пользователем могут со временем меняться, но HTML должен быть достаточно гибким (IMHO), чтобы охватить любой видимый сценарий.
MaxZoom

Ответы:

529

Начиная с w3: сам ярлык может располагаться до, после или вокруг соответствующего элемента управления.

<label for="lastname">Last Name</label>
<input type="text" id="lastname" />

или

<input type="text" id="lastname" />
<label for="lastname">Last Name</label>

или

<label>
   <input type="text" name="lastname" />
   Last Name
</label>

Обратите внимание, что третий метод нельзя использовать, когда для макета используется таблица с меткой в ​​одной ячейке и связанным с ней полем формы в другой ячейке.

Любой из них действителен. Мне нравится использовать первый или второй пример, так как он дает больше контроля над стилем.

superUntitled
источник
14
Как ответили, все они действительны, но в моей собственной практике я обычно выбираю первый пример, приведенный здесь как superUntitled для текстовых полей, текстовых полей и селектов. Но для переключателей и флажков я обычно использую третий пример, где я хочу ввод перед сопроводительным текстом и не хочу того же типа фиксированной ширины и / или плавающего, который используют остальные метки и поля. Так что в любой отдельной форме вы можете найти меня, использующего оба этих формата вместе.
Funka
6
Интересно, если <label for="inputbox"><input id="inputbox" type="text" /></label>это пропуск по их критериям?
Мэтт
64
Жаль, что вы не можете вложить метку в тег ввода. Было бы гораздо более семантически рациональным, поскольку метка действительно является свойством ввода, если вы видите это с абстрактной точки зрения.
Алекс
9
Связанный документ WCAG включает следующую опцию «Элемент управления содержится в элементе метки, который содержит текст метки». Я не знаю, было ли это добавлено за годы, прошедшие после того, как @Sorcy прокомментировал, но сценарий ввода в метке сейчас считается действительным.
Алекс Вайцер
6
Существует проблема с вводом внутри метки, по крайней мере, в Chrome, когда вы присоединяете обработчик события щелчка к метке, при нажатии метки обработчик запускается дважды. Вы можете справиться с этим return false;в конце обработчика, но если у вас, возможно, есть другие обработчики, которые необходимо выполнить впоследствии, и остановка распространения не является опцией, это становится проблемой.
wired_in
67

я предпочитаю

<label>
  Firstname
  <input name="firstname" />
</label>

<label>
  Lastname
  <input name="lastname" />
</label>

над

<label for="firstname">Firstname</label>
<input name="firstname" id="firstname" />

<label for="lastname">Lastname</label>
<input name="lastname" id="lastname" />

Главным образом потому, что это делает HTML более читабельным. И я на самом деле думаю, что мой первый пример легче стилизовать с помощью CSS, так как CSS очень хорошо работает с вложенными элементами.

Но это вопрос вкуса, я полагаю.


Если вам нужны дополнительные параметры стиля, добавьте тег span.

<label>
  <span>Firstname</span>
  <input name="firstname" />
</label>

<label>
  <span>Lastname</span>
  <input name="lastname" />
</label>

Код все еще выглядит лучше, на мой взгляд.

Znarkus
источник
3
Включение ввода внутри метки аналогично использованию HTML для макета.
Эмиль
8
Мне нравится это решение также для таких случаев: <label>Expires after <input name="exp" /> days</label>(метка находится до и после элемента ввода)
Philipp
Я думаю, что последний пример - кроме атрибутов for и id - на самом деле ничем не отличается от наличия метки рядом со входом и того, что оба обернуты в a div, liили нет, не так ли?
ретровертиго
1
@retrovertigo - функционально? Нет. Это просто уменьшает разметку и уменьшает семантическое злоупотребление терминами. Мы знаем, что ввод firstnameдолжен следовать за меткой firstname, но браузерам нужно объявление. Это все дело вкуса и того, что вы думаете, выглядит лучше (и легче всего отлаживается) в вашем коде. Я предпочитаю использовать nested сейчас, хотя мне потребовалось некоторое время, чтобы привыкнуть к нему.
Xhynk
3
@MPavlak - быстрый взгляд, и я нашел это руководство от w3.org. w3.org/WAI/tutorials/forms/labels . Затем я проверил w3.org/TR/WCAG20-TECHS/H44.html . Внизу (это неясно) написано, что для того, чтобы претендовать на соответствие, вам необходимо пройти тестовые критерии, и в нем конкретно указано, что вы должны использовать атрибут for. На самом деле, когда я в последний раз проверял это в Apple Voiceover (10% доли рынка десктопов, 60% доли рынка мобильных устройств) неявные ярлыки не работали, так что это был еще один важный фактор. Надеюсь, это поможет!
Джеймс Вестгейт
39

Если вы включите тег ввода в тег label, вам не нужно использовать атрибут «for».

Тем не менее, я не люблю включать тег ввода в свои метки, потому что я думаю, что они являются отдельными, не содержащими сущности.

Терри
источник
8
Для for требуется, чтобы вы использовали идентификатор, что делает иерархическое структурирование очень сложным :-(
lethalman
39

Разница в поведении: щелчок в пространстве между меткой и вводом

Если щелкнуть пробел между меткой и входом, он активирует вход, только если метка содержит вход.

Это имеет смысл, поскольку в этом случае пробел является просто еще одним символом метки.

<p>Inside:</p>

<label>
  <input type="checkbox" />
  |&lt;----- Label. Click between me and the checkbox.
</label>

<p>Outside:</p>

<input type="checkbox" id="check" />
<label for="check">|&lt;----- Label. Click between me and the checkbox.</label>

Возможность щелкать между ярлыком и полем означает, что это:

  • легче нажать
  • менее ясно, где все начинается и заканчивается

Чекбокс Bootstrap v3.3 примеры используют входные данные внутри: http://getbootstrap.com/css/#forms Может быть, стоит следовать им. Но они изменили свое мнение в v4.0 https://getbootstrap.com/docs/4.0/components/forms/#checkboxes-and-radios, поэтому я не знаю, что мудрее больше:

Флажки и радио используются для поддержки валидации форм на основе HTML и обеспечения кратких, доступных меток. Таким образом, наши <input>s и <label>s являются родственными элементами, а не <input>внутри a <label>. Это немного более многословно, так как вы должны указать id и атрибуты, чтобы связать <input>и <label>.

Вопрос UX, в котором подробно обсуждается этот момент: /ux/23552/should-the-space-between-the-checkbox-and-label-be-clickable

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
источник
Это не специфика разницы. Переключатель работает в обоих случаях во всех совместимых браузерах.
hexalys
@hexalys Спасибо за отчет. Я обновил ответ. Вы имеете в виду, что совместимые браузеры должны переключаться или нет в обоих случаях? Если бы вы могли дать ссылку на соответствующий стандартный отрывок, это было бы замечательно.
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
1
Да. Хотя я не заметил, что ваш пример вводит в заблуждение, потому что ваше пространство не является текстовым пространством . Это marginиз флажка. Поведение Firefox на вашем примере является своеобразным и кажется ошибкой. A labelбудет содержать пробелы или отступы вокруг встроенного содержимого как кликабельные. Но, учитывая, что модель содержимого метки является встроенным / фразовым содержимым, поле ввода не должно быть кликабельным, если только ваша метка не создана, и display: blockв этом случае внутренняя часть метки blockстановится кликабельной во всех браузерах.
hexalys
1
Обратите внимание, что ссылка Bootstrap в ответе идет в документах для v3.3. В документы для v4.0 , кажется, указывают , что они изменили свое мнение:. «Флажки и радио использовать построены для валидации форм поддержки HTML на основе и представлять краткие, доступные ярлыки Таким образом , наш <вход> s и <метка> s являются родственными элементами в отличие от <input> внутри <label>. Это немного более многословно, так как вы должны указать id и атрибуты, чтобы связать <input> и <label> ".
Майкл Кребс
2
Эта разница в поведении является большой для меня. Когда элементы являются одноуровневыми, любое поле на любом из этих элементов уменьшает площадь интерактивной поверхности, которая вызывает элемент ввода. Вложенные данные внутри метки сохраняют максимальную область, доступную для щелчка, обеспечивая максимальный доступ даже для пользователей, которые испытывают трудности с точными движениями мыши или касания. В Bootstrap 4 вложение все еще работает и по-прежнему отображает то же самое без необходимости настраивать или переопределять любой Bootstrap CSS.
Тургс
17

Лично мне нравится держать ярлык снаружи, как во втором примере. Вот почему есть атрибут FOR. Причина в том, что я часто применяю стили к метке, например ширину, чтобы форма выглядела хорошо (сокращение ниже):

<style>
label {
  width: 120px;
  margin-right: 10px;
}
</style>

<label for="myinput">My Text</label>
<input type="text" id="myinput" /><br />
<label for="myinput2">My Text2</label>
<input type="text" id="myinput2" />

Делает так, чтобы я мог избежать таблиц и всего такого барахла в моих формах.

Попугаи
источник
3
Разве вы не должны оставлять презентацию в CSS, а не использовать <br />для разделения входов?
Знаркус
1
@Znarkus - да, обычно я оборачиваю их в OL / LI, чтобы иметь дело с таким форматированием, это был всего лишь быстрый сокращенный пример.
Попугаи
1
@Parrots: Семантически, в этом нет смысла. И если вам нужно обернуть их, почему бы просто не обернуть их этикеткой?
Знаркус
1
@Parrots С этим рассуждением я думаю, что все на странице должно идти внутрь ul / li. И у <label> <span>My text</span> <input /> </label>вас есть все варианты стилей, которые вам (когда-либо) понадобятся.
Знаркус
1
Использование «for» заставляет вас использовать идентификатор, что плохо для иерархических макетов.
летчик
15

См. Http://www.w3.org/TR/html401/interact/forms.html#h-17.9 для рекомендаций W3.

Они говорят, что это может быть сделано в любом случае. Они описывают два метода как явный (используя «for» с идентификатором элемента) и неявный (встраивание элемента в метку):

Явный:

Атрибут for явно связывает метку с другим элементом управления: значение атрибута for должно совпадать со значением атрибута id соответствующего элемента управления.

Неявные:

Чтобы неявно связать метку с другим элементом управления, элемент управления должен находиться внутри содержимого элемента LABEL. В этом случае LABEL может содержать только один элемент управления.

user470514
источник
Я только что обнаружил, что неявное не работает в IE ... какие-нибудь идеи?
Каринлинчин
11

Оба являются правильными, но размещение ввода внутри метки делает его гораздо менее гибким при стилизации с помощью CSS.

Во- первых, ограничено , в котором элементы он может содержать . Например, вы можете поместить только между и надписью текст, если не находится внутри .<label><div><input><input><label>

Во-вторых, хотя существуют обходные пути для упрощения стиля, например, обтекание текста внутренней метки диапазоном, некоторые стили будут наследоваться от родительских элементов, что может усложнить стилизацию.

nicholaides
источник
гораздо менее гибким? можешь уточнить? как уже упоминали другие, вы можете просто обернуть текст внутренней метки в интервал, если это не делает его намного менее гибким?
MPavlak
7

Заметное значение 'gotcha' требует, чтобы вы никогда не включали более одного элемента ввода в элемент <label> с явным атрибутом "for", например:

<label for="child-input-1">
  <input type="radio" id="child-input-1"/>
  <span> Associate the following text with the selected radio button: </span>
  <input type="text" id="child-input-2"/>
</label>

Хотя это может показаться заманчивым для элементов формы, в которых пользовательское текстовое значение является вторичным по отношению к переключателю или флажку, функциональность click-focus элемента label немедленно переместит фокус на элемент, идентификатор которого явно определен в его атрибуте 'for' , что делает практически невозможным для пользователя щелкнуть в текстовом поле, чтобы ввести значение.

Лично я стараюсь избегать элементов меток с входными дочерними элементами. Семантически неуместно, когда элемент label охватывает больше, чем сам ярлык. Если вы вкладываете входные данные в метки для достижения определенной эстетики, вам следует вместо этого использовать CSS.

Аарон
источник
4
Это не "готча". Это явно часть спецификации; этикетка может содержать до 1 элемента управления. Здесь вы также смешиваете неявные и явные стили - если вы помещаете элемент управления в метку, вам это не нужно for... и если вы хотите его использовать for, то наличие элемента управления внутри метки не имеет особого смысла. ,
Chao
Правда, но, похоже, эта спецификация не совсем понятна. Мы столкнулись с этой проблемой с API форм Drupal 6, который генерировал разметку, которая создавала сценарий, не похожий на описанный выше. Это заставило моего коллегу и меня почесать голову в течение минуты или двух, поэтому я решил сообщить об этом здесь, чтобы избежать потенциальной путаницы в будущем.
Аарон
нет необходимости "для" в метке-> входной сценарий. один ввод для каждой метки, и его преимущество состоит в том, что вам не нужно знать имя или идентификатор, и вы можете сделать хороший стиль CSS, чтобы сохранить вещи инкапсулированными, а также иметь фокусировку, возникающую при нажатии любого другого элемента, такого как внутри. см. zipstory.com/signup для примера чистого способа сделать это.
Джейсон Себринг
Спасибо; это ответило на еще один связанный с этим вопрос, а именно: возможно ли, чтобы внутри метки было больше одного ввода? (Контекст: несколько опций переключателей, по одному на строку, каждая запись переключателя имеет 1, 2, 3 или, возможно, больше вводов типа text, с намерением щелкнуть строку, имеющую результат выбора переключателя этой строки, если не выбран, и позволяет редактировать ввод / ввод в этой строке.) Это оставляет дверь открытой для наличия нескольких меток для не введенного текста в форме, но она ответила на мой вопрос о том, было ли то, что я думал, в порядке. (Это не было.)
Христос Хейворд
6

Как говорили большинство людей, оба способа действительно работают, но я думаю, что только первый должен. Будучи семантически строгим, метка не «содержит» входные данные. На мой взгляд, отношение содержания (родитель / ребенок) в структуре разметки должно отражать содержание в визуальном выводе . т.е. элемент, окружающий другой элемент в разметке, должен быть нарисован вокруг этого элемента в браузере . В соответствии с этим, метка должна быть родственной, а не родительской. Так что вариант номер два произвольный и запутанный. Все, кто читал Zen of Python , вероятно, согласятся (Flat лучше, чем вложенный, Sparse лучше, чем плотный, должен быть один - и желательно только один - очевидный способ сделать это ...).

Из-за решений, подобных этому от W3C и основных поставщиков браузеров (позволяющих «в зависимости от того, как вы предпочитаете это делать», а не «делайте это правильно»), Интернет сегодня настолько запутан, и нам, разработчикам, приходится иметь дело с запутанными и так разнообразный унаследованный код.

slashCoder
источник
5

Я обычно иду с первыми двумя вариантами. Я видел сценарий, когда использовался третий вариант, когда выбор радио включался в метки и CSS содержал что-то вроде

label input {
    vertical-align: bottom;
}

чтобы обеспечить правильное вертикальное выравнивание для радиостанций.

Виктор Ионеску
источник
2

Я предпочитаю оборачивать элементы внутри себя, <label>потому что мне не нужно генерировать идентификаторы.

Я разработчик Javascript, и React или Angular используются для генерации компонентов, которые могут быть использованы мной или другими пользователями. Тогда будет легко дублировать идентификатор на странице, что приведет к странному поведению.

Николас Зозол
источник
1

Одна вещь, которую вы должны рассмотреть, это взаимодействие флажка и радиовходов с javascript.

Используя структуру ниже:

<label>
  <input onclick="controlCheckbox()" type="checkbox" checked="checkboxState" />
  <span>Label text</span>
</label>

Когда пользователь нажимает на «Текст метки», функция controlCheckbox () запускается один раз.

Но при нажатии входного тега функция controlCheckbox () может запускаться дважды в некоторых старых браузерах. Это связано с тем, что теги input и label запускают событие onclick, прикрепленное к флажку.

Тогда у вас могут быть некоторые ошибки в вашем checkboxState.

Я столкнулся с этой проблемой в последнее время на IE11. Я не уверен, что современные браузеры имеют проблемы с этой структурой.

Мариуш
источник
-1

Основным преимуществом размещения inputвнутри labelявляется эффективность печати для людей и хранение байтов для компьютеров.

@Znarkus сказал в своем комментарии к OP,

Один из больших плюсов размещения <input />внутри <label>, это то, что вы можете опустить forи id: <label>My text <input /></label>в вашем примере. Так намного лучше!

Примечание: в коде @Znarknus была включена другая эффективность, не указанная явно в комментарии. type="text"также может быть опущен и inputбудет отображать текстовое поле по умолчанию.

Совместное сравнение нажатий клавиш и байтов [1].

31 нажатие клавиши, 31 байт

<label>My Text<input /></label>

58 нажатий клавиш, 58 байт

<label for="myinput">My Text</label><input id="myinput" />

В противном случае фрагменты визуально равны, и они предлагают тот же уровень доступности для пользователя. Пользователь может щелкнуть или коснуться метки, чтобы поместить курсор в текстовое поле.

[1] Текстовые файлы (.txt), созданные в блокноте в Windows, в байтах из свойств проводника Windows

ThisClark
источник