Dois-je mettre des éléments d'entrée dans un élément d'étiquette?

606

Existe-t-il une meilleure pratique concernant l'imbrication des éléments HTML labelet input?

manière classique:

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

ou

<label for="myinput">My Text
   <input type="text" id="myinput" />
</label>
jpsimard-nyx
la source
107
L'un des grands avantages de mettre l' <input />intérieur <label>, c'est que vous pouvez omettre foret id: <label>My text <input /></label>dans votre exemple. Tant mieux!
Znarkus
16
Bien que je convienne que cela inputn'appartient pas sémantiquement à l'intérieur d'un label, j'ai remarqué aujourd'hui que les développeurs de Bootstrap n'étaient pas d'accord avec moi . Certains éléments, tels que les cases à cocher en ligne, sont de style différent selon qu'ils inputsont à l'intérieur ou à l'extérieur.
Blazemonger
6
BTW c'était une très mauvaise idée à créer <label for="id">car j'ai plusieurs formulaires sur la page et je ne peux pas utiliser d' idattribut pour de nombreux widgets sans tomber dans le unique id per pagepiège. La seule façon acceptable d'accéder au widget est par form + widget_name.
MaxZoom
5
@MaxZoom si vous avez tellement de formulaires différents sur votre page avec des noms de champs identiques que vous avez du mal à trouver des ID uniques, vous voudrez peut-être reconsidérer un peu la conception de votre page, à mon humble avis; évidemment , je ne connais pas votre situation, mais que tout simplement les mauvaises odeurs me
Ken Bellows
5
@kenbellows C'est une idée de designer / entreprise (pas la mienne) de mettre deux formulaires de recherche sur une seule page. Les meilleures pratiques en matière d'expérience utilisateur peuvent changer avec le temps, mais le code HTML doit être suffisamment flexible (à mon humble avis) pour couvrir tout scénario visible.
MaxZoom

Réponses:

529

À partir de w3: l'étiquette elle-même peut être positionnée avant, après ou autour du contrôle associé.

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

ou

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

ou

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

Notez que la troisième technique ne peut pas être utilisée lorsqu'un tableau est utilisé pour la mise en page, avec l'étiquette dans une cellule et son champ de formulaire associé dans une autre cellule.

L'un ou l'autre est valide. J'aime utiliser le premier ou le deuxième exemple, car cela vous donne plus de contrôle sur le style.

superUntitled
la source
14
Comme répondu, tous sont valides mais dans ma propre pratique, je me contente généralement du premier exemple donné ici par superUntitled pour les zones de texte, les zones de texte et les sélections. Mais pour les boutons radio et les cases à cocher, j'utilise généralement le troisième exemple, où je veux l'entrée avant le texte d'accompagnement et ne veux pas le même type de largeur fixe et / ou flottante que le reste des étiquettes et des champs utilisent. Donc, sur n'importe quelle forme donnée, vous pourriez me trouver en utilisant ces deux formats ensemble.
Funka
6
Je me demande si <label for="inputbox"><input id="inputbox" type="text" /></label>c'est un pass selon leurs critères.
Matt
64
Dommage que vous ne puissiez pas imbriquer une étiquette à l'intérieur d'une balise d'entrée. Ce serait beaucoup plus sémantiquement rationnel, puisque l'étiquette est vraiment une propriété de l'entrée, si vous la voyez d'un point de vue abstrait.
Alex
9
Le document WCAG lié comprend l'option suivante «Le contrôle est contenu dans un élément d'étiquette qui contient le texte de l'étiquette». Je ne sais pas si cela a été ajouté dans les années depuis que @Sorcy a commenté, mais le scénario d'entrée dans l'étiquette est considéré comme valide maintenant.
Alex Weitzer
6
Il y a un problème avec l'entrée à l'intérieur de l'étiquette, au moins dans Chrome, lorsque vous attachez un gestionnaire d'événements Click à l'étiquette, le gestionnaire est déclenché deux fois lorsque vous cliquez sur l'étiquette. Vous pouvez vous en tirer avec return false;à la fin du gestionnaire, mais si vous avez éventuellement d'autres gestionnaires qui doivent s'exécuter par la suite, et l'arrêt de la propagation n'est pas une option, cela devient un problème.
wired_in
67

je préfère

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

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

plus de

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

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

Principalement parce que cela rend le HTML plus lisible. Et je pense en fait que mon premier exemple est plus facile à styliser avec CSS, car CSS fonctionne très bien avec les éléments imbriqués.

Mais c'est une question de goût je suppose.


Si vous avez besoin de plus d'options de style, ajoutez une balise span.

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

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

Le code semble toujours meilleur à mon avis.

Znarkus
la source
3
L'inclusion de l'entrée à l'intérieur de l'étiquette revient à utiliser HTML pour la mise en page.
Emil
8
J'aime cette solution également pour des cas comme celui-ci: <label>Expires after <input name="exp" /> days</label>(l'étiquette est avant et après l'élément d'entrée)
Philipp
Je pense que le dernier exemple est - en plus des attributs for et id - pas vraiment différent d'avoir l'étiquette à côté de l'entrée et les deux enveloppés dans un div, liou quoi, n'est-ce pas?
retrovertigo
1
@retrovertigo - fonctionnellement? Non. Cela réduit simplement le balisage et réduit la surutilisation sémantique des termes. Nous savons que l'entrée firstnamedoit suivre l'étiquette firstname, mais les navigateurs ont besoin de la déclaration. Tout est une question de goût et de ce que VOUS pensez être le mieux (et le plus facile à déboguer) dans votre code. Je préfère utiliser imbriqué maintenant, même s'il m'a fallu un certain temps pour m'y habituer.
Xhynk
3
@MPavlak - un coup d'œil rapide et j'ai trouvé ces conseils de w3.org. w3.org/WAI/tutorials/forms/labels . J'ai ensuite vérifié w3.org/TR/WCAG20-TECHS/H44.html . En bas (il est obscur), il indique que pour revendiquer la conformité, vous devez passer les critères de test, et cela indique spécifiquement que vous devez utiliser l'attribut for. En réalité, lors de mon dernier test sur Apple Voiceover (10% de part de marché pour les lecteurs d'écran de bureau, 60% de part de marché pour les lecteurs d'écran de mobile), les étiquettes implicites ne fonctionnaient pas, c'était donc un autre facteur majeur. J'espère que cela pourra aider!
James Westgate
39

Si vous incluez la balise d'entrée dans la balise label, vous n'avez pas besoin d'utiliser l'attribut 'for'.

Cela dit, je n'aime pas inclure la balise d'entrée dans mes étiquettes car je pense que ce sont des entités séparées, ne contenant pas d'entités.

Terry
la source
8
Le for nécessite cependant que vous
utilisiez
39

Différence de comportement: cliquer dans l'espace entre l'étiquette et l'entrée

Si vous cliquez sur l'espace entre l'étiquette et l'entrée, elle active l'entrée uniquement si l'étiquette contient l'entrée.

Cela est logique car dans ce cas, l'espace n'est qu'un autre caractère de l'étiquette.

<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>

Pouvoir cliquer entre l'étiquette et la boîte signifie que c'est:

  • plus facile à cliquer
  • moins clair où les choses commencent et se terminent

Les exemples de la case à cocher Bootstrap v3.3 utilisent l'entrée à l'intérieur: http://getbootstrap.com/css/#forms Il pourrait être judicieux de les suivre. Mais ils ont changé d'avis dans la v4.0 https://getbootstrap.com/docs/4.0/components/forms/#checkboxes-and-radios donc je ne sais plus ce qui est sage:

Les cases à cocher et les radios sont conçues pour prendre en charge la validation de formulaire HTML et fournir des étiquettes concises et accessibles. En tant que tels, nos <input>s et <label>s sont des éléments frères par opposition à un <input>dans un <label>. Ceci est légèrement plus détaillé car vous devez spécifier id et pour que les attributs relient le <input>et <label>.

Question UX qui traite de ce point en détail: /ux/23552/should-the-space-between-the-checkbox-and-label-be-clickable

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
Ce n'est pas une différence de spécification. La bascule fonctionne pour les deux cas dans tous les navigateurs compatibles.
hexalys
@hexalys Merci pour le rapport. J'ai mis à jour la réponse. Voulez-vous dire que les navigateurs conformes devraient basculer ou non dans les deux cas? Si vous pouviez créer un lien vers le passage standard pertinent, ce serait génial.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Oui. Bien que je n'aie pas remarqué que votre exemple est trompeur car votre espace n'est pas vraiment un espace de texte . C'est une margincase à cocher. Le comportement de Firefox sur votre exemple est particulier et ressemble à un bogue. A labelcontiendra les espaces ou le remplissage autour du contenu en ligne comme cliquable. Mais étant donné que le modèle de contenu d'une étiquette est un contenu en ligne / de formulation, la marge d'entrée ne doit pas être cliquable, sauf si votre étiquette est créée,display: block auquel cas l'intérieur de l'étiquette blockdevient cliquable dans tous les navigateurs.
hexalys
1
Notez que le lien Bootstrap dans la réponse va aux documents pour v3.3. Les documents pour v4.0 semblent indiquer qu'ils ont changé d'avis: «Les cases à cocher et les radios sont conçues pour prendre en charge la validation de formulaire HTML et fournir des étiquettes concises et accessibles. En tant que telles, nos <input> s et <label> s sont des éléments frères par opposition à un <input> dans un <label>. Ceci est légèrement plus détaillé car vous devez spécifier id et pour que les attributs relient le <input> et le <label> ".
Michael Krebs
2
Cette différence de comportement est la plus importante pour moi. Lorsque les éléments sont frères et sœurs, toute marge sur l'un ou l'autre élément réduit la surface cliquable qui déclenchera l'élément d'entrée. L'imbrication de l'entrée à l'intérieur de l'étiquette préserve la zone cliquable maximale, offrant une accessibilité maximale même pour les utilisateurs qui ont du mal avec des mouvements précis de la souris ou du toucher. Dans Bootstrap 4, l'imbrication fonctionne toujours et affiche toujours la même chose sans avoir besoin d'ajuster ou de remplacer un CSS Bootstrap.
Turgs
17

Personnellement, j'aime garder l'étiquette à l'extérieur, comme dans votre deuxième exemple. C'est pourquoi l'attribut FOR est là. La raison étant que je vais souvent appliquer des styles à l'étiquette, comme une largeur, pour que le formulaire soit joli (raccourci ci-dessous):

<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" />

Fait en sorte que je puisse éviter les tableaux et toutes ces ordures dans mes formulaires.

Perroquets
la source
3
Ne devriez-vous pas laisser la présentation au CSS, au lieu d'utiliser <br />pour séparer les entrées?
Znarkus
1
@Znarkus - oui, normalement je les encapsule dans des OL / LI pour gérer un formatage comme ça, ce n'était qu'un exemple rapide.
Parrots
1
@Parrots: Cela n'a pas beaucoup de sens sémantiquement, imo. Et si vous avez besoin de les envelopper, pourquoi ne pas simplement les envelopper avec l'étiquette?
Znarkus le
1
@Parrots Avec ce raisonnement, je pense que tout sur une page devrait aller dans ul / li. Et avec <label> <span>My text</span> <input /> </label>vous, vous avez toutes les options de style dont vous auriez (jamais) besoin.
Znarkus
1
L'utilisation de "for" vous oblige à utiliser un identifiant, ce qui est mauvais pour les dispositions hiérarchiques.
lethalman
15

Voir http://www.w3.org/TR/html401/interact/forms.html#h-17.9 pour les recommandations W3.

Ils disent que cela peut être fait de toute façon. Ils décrivent les deux méthodes comme explicites (en utilisant "pour" avec l'identifiant de l'élément) et implicites (en incorporant l'élément dans l'étiquette):

Explicite:

L'attribut for associe explicitement une étiquette à un autre contrôle: la valeur de l'attribut for doit être la même que la valeur de l'attribut id de l'élément de contrôle associé.

Implicite:

Pour associer une étiquette à un autre contrôle implicitement, l'élément de contrôle doit se trouver dans le contenu de l'élément LABEL. Dans ce cas, LABEL ne peut contenir qu'un seul élément de contrôle.

user470514
la source
Je viens de découvrir que l'implicite ne fonctionne pas dans IE ... toutes les idées?
carinlynchin
11

Les deux sont corrects, mais mettre l'entrée à l'intérieur de l'étiquette le rend beaucoup moins flexible lors du style avec CSS.

Tout d'abord, a <label>est limité dans les éléments qu'il peut contenir . Par exemple, vous ne pouvez mettre un <div>entre le <input>et le texte de l'étiquette que si le <input>n'est pas à l'intérieur du <label>.

Deuxièmement, bien qu'il existe des solutions de contournement pour rendre le style plus facile, comme habiller le texte de l'étiquette intérieure avec une étendue, certains styles seront hérités des éléments parents, ce qui peut rendre le style plus compliqué.

nicholaides
la source
beaucoup moins flexible? peux-tu élaborer? comme d'autres l'ont mentionné, vous pouvez simplement envelopper le texte de l'étiquette intérieure avec une étendue, sauf si c'est ce qui le rend beaucoup moins flexible?
MPavlak
7

Un "gotcha" notable dicte que vous ne devez jamais inclure plus d'un élément d'entrée à l'intérieur d'un élément <label> avec un attribut "for" explicite, par exemple:

<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>

Bien que cela puisse être tentant pour les fonctionnalités de formulaire dans lesquelles une valeur de texte personnalisée est secondaire à un bouton radio ou à une case à cocher, la fonctionnalité de mise au point du clic de l'élément d'étiquette jettera immédiatement le focus à l'élément dont l'ID est explicitement défini dans son attribut `` pour '' , ce qui rend presque impossible pour l'utilisateur de cliquer dans le champ de texte contenu pour entrer une valeur.

Personnellement, j'essaie d'éviter les éléments d'étiquette avec des enfants d'entrée. Il semble sémantiquement inapproprié qu'un élément d'étiquette englobe plus que l'étiquette elle-même. Si vous imbriquez des entrées dans des étiquettes afin d'obtenir une certaine esthétique, vous devriez plutôt utiliser CSS.

Aaron
la source
4
Ce n'est pas un "gotcha". Cela fait explicitement partie de la spécification; l'étiquette peut contenir jusqu'à 1 contrôle. Vous mélangez également les styles implicites et explicites ici - si vous mettez le contrôle à l'intérieur de l'étiquette, vous n'avez pas besoin for... et si vous voulez utiliser for, alors avoir le contrôle à l'intérieur de l'étiquette n'a pas beaucoup de sens .
cHao
Certes, mais il semblerait que cette spécification ne soit pas bien comprise. Nous avons rencontré ce problème avec l'API Forms de Drupal 6, qui a généré un balisage qui a créé un scénario similaire à celui décrit ci-dessus. Mon collègue et moi nous sommes gratté la tête pendant une minute ou deux, alors j'ai pensé que j'exposerais le problème ici pour éviter toute confusion potentielle à l'avenir.
Aaron
pas besoin de "pour" dans le scénario d'entrée label->. une entrée par étiquette et cela a l'avantage de ne pas avoir à connaître le nom ou l'id et vous pouvez faire un joli style CSS pour garder les choses encapsulées ainsi que pour que la mise au point se produise lorsque vous cliquez sur un autre élément de ce type. voir zipstory.com/signup pour un exemple de façon propre de le faire.
Jason Sebring
Je vous remercie; cela a répondu à une autre question connexe que j'avais, à savoir s'il y aurait potentiellement plus d'une entrée dans une étiquette. (Contexte: plusieurs options de bouton radio, une par ligne, chaque entrée de bouton radio ayant 1, 2, 3 ou éventuellement plusieurs entrées de type texte, avec l'intention de cliquer sur une ligne ayant pour résultat de sélectionner le bouton radio de cette ligne, si non sélectionné et permettant la modification des entrées / entrées sur cette ligne.) Cela laisse la porte ouverte à plusieurs étiquettes pour le texte non entré dans le formulaire, mais cela a répondu à ma question de savoir si ce que je pensais était OK. (Ce n'était pas le cas.)
Christos Hayward
6

Comme la plupart des gens l'ont dit, les deux méthodes fonctionnent effectivement, mais je pense que seule la première devrait l'être. Étant sémantiquement strict, l'étiquette ne "contient" pas l'entrée. À mon avis, la relation de confinement (parent / enfant) dans la structure de balisage devrait refléter le confinement dans la sortie visuelle . c'est-à-dire qu'un élément entourant un autre dans le balisage doit être tracé autour de celui-ci dans le navigateur . Selon cela, l'étiquette devrait être le frère de l'entrée, pas son parent. L'option numéro deux est donc arbitraire et déroutante. Tous ceux qui ont lu le Zen de Python seront probablement d'accord (Flat est meilleur que imbriqué, Sparse vaut mieux que dense, Il devrait y en avoir une - et de préférence une seule - une façon évidente de le faire ...).

En raison de décisions telles que celles du W3C et des principaux fournisseurs de navigateurs (autorisant "la façon dont vous préférez le faire", au lieu de "le faire de la bonne manière"), le Web est tellement foiré aujourd'hui et nous, les développeurs, devons faire face à des problèmes et un code hérité si diversifié.

slashCoder
la source
5

Je choisis généralement les deux premières options. J'ai vu un scénario lorsque la troisième option a été utilisée, lorsque les choix radio étaient intégrés dans les étiquettes et le CSS contenait quelque chose comme

label input {
    vertical-align: bottom;
}

afin d'assurer un bon alignement vertical des radios.

Victor Ionescu
la source
2

Je préfère grandement envelopper les éléments dans mon <label>car je n'ai pas à générer les identifiants.

Je suis un développeur Javascript et React ou Angular sont utilisés pour générer des composants qui peuvent être réutilisés par moi ou par d'autres. Il serait alors facile de dupliquer un identifiant dans la page, ce qui entraînerait des comportements étranges.

Nicolas Zozol
la source
1

Une chose que vous devez considérer est l'interaction des cases à cocher et des entrées radio avec javascript.

En utilisant la structure ci-dessous:

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

Lorsque l'utilisateur clique sur "Texte du libellé", la fonction controlCheckbox () est déclenchée une fois.

Mais lorsque la balise d'entrée est cliquée, la fonction controlCheckbox () peut être déclenchée deux fois dans certains navigateurs plus anciens. En effet, les balises d'entrée et d'étiquette déclenchent un événement onclick attaché à la case à cocher.

Ensuite, vous pouvez avoir des bogues dans votre checkboxState.

J'ai rencontré ce problème récemment sur IE11. Je ne sais pas si les navigateurs modernes ont des problèmes avec cette structure.

Mariusz
la source
-1

Le principal avantage de placer à l' inputintérieur delabel est l'efficacité de la frappe pour les humains et le stockage des octets pour les ordinateurs.

@Znarkus a déclaré dans son commentaire au PO,

L'un des grands avantages de mettre l' <input />intérieur <label>, c'est que vous pouvez omettre foret id: <label>My text <input /></label>dans votre exemple. Tant mieux!

Remarque: Dans le code @Znarknus, une autre efficacité a été incluse non explicitement indiquée dans le commentaire. type="text"peut également être omis et inputaffichera une zone de texte par défaut.

Une comparaison côte à côte des frappes et des octets [1].

31 frappes, 31 octets

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

58 touches, 58 octets

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

Sinon, les extraits sont visuellement égaux et offrent le même niveau d'accessibilité aux utilisateurs. Un utilisateur peut cliquer ou toucher l'étiquette pour placer le curseur dans la zone de texte.

[1] Fichiers texte (.txt) créés dans le Bloc-notes sous Windows, octets des propriétés de l'Explorateur de fichiers Windows

ThisClark
la source