Devo colocar elementos de entrada dentro de um elemento de rótulo?

606

Existe uma melhor prática sobre a nidificação de labele inputelementos HTML?

maneira clássica:

<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
fonte
107
Um dos grandes profissionais de colocar o <input />interior de <label>, é que você pode omitir fore id: <label>My text <input /></label>no seu exemplo. Muito melhor!
Znarkus 11/09/11
16
Embora eu concorde que inputnão pertence semanticamente a um label, notei hoje que os desenvolvedores do Bootstrap discordam de mim . Alguns elementos, como caixas de seleção embutidas, têm um estilo diferente, dependendo de inputestar dentro ou fora.
Blazemonger
6
BTW, essa foi uma péssima idéia para criar, <label for="id">pois tenho vários formulários na página e não posso usar o idatributo para muitos widgets sem cair na unique id per pagearmadilha. A única maneira aceitável de acessar o widget é por form + widget_name.
MaxZoom 22/09
5
@ MaxZoom Se você tem tantos formulários diferentes em sua página com nomes de campos idênticos que está tendo problemas para criar IDs únicos, convém reconsiderar um pouco o design da página, IMHO; obviamente, eu não sei a sua situação, mas que só cheira mal para mim
Ken Bellows
5
@kenbellows É uma idéia de designer / empresa (não minha) colocar dois formulários de pesquisa em uma página. As melhores práticas de experiência do usuário podem mudar com o tempo, mas o HTML deve ser flexível o suficiente (IMHO) para cobrir qualquer cenário visível.
MaxZoom

Respostas:

529

De w3: o próprio rótulo pode ser posicionado antes, depois ou ao redor do controle associado.

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

Observe que a terceira técnica não pode ser usada quando uma tabela está sendo usada para layout, com o rótulo em uma célula e seu campo de formulário associado em outra célula.

Qualquer um é válido. Eu gosto de usar o primeiro ou o segundo exemplo, pois oferece mais controle de estilo.

superUntitled
fonte
14
Como respondido, todos são válidos, mas, em minha própria prática, geralmente me deparo com o primeiro exemplo dado aqui por superUntitled para caixas de texto, áreas de texto e seleções. Mas, para botões de opção e caixas de seleção, geralmente uso o terceiro exemplo, onde desejo a entrada antes do texto que o acompanha e não quero o mesmo tipo de largura fixa e / ou flutuante que o restante dos rótulos e campos estão usando. Portanto, em qualquer formulário, você pode me encontrar usando esses dois formatos juntos.
Funka,
6
Gostaria de saber se <label for="inputbox"><input id="inputbox" type="text" /></label>é um passe de acordo com seus critérios.
Matt
64
Pena que você não pode aninhar um rótulo dentro de um tag de entrada. Seria muito mais semanticamente racional, já que o rótulo é realmente uma propriedade da entrada, se você o vir de um ponto de vista abstrato.
21414 Alex
9
O documento WCAG vinculado inclui a seguinte opção "O controle está contido em um elemento de rótulo que contém o texto do rótulo". Não sei se isso foi adicionado nos anos desde que o @Sorcy comentou, mas o cenário de entrada no rótulo é considerado válido agora.
Alex Weitzer
6
Há um problema com a entrada dentro do rótulo, pelo menos no chrome, quando você anexa um manipulador de eventos de clique ao rótulo, o manipulador é acionado duas vezes quando o rótulo é clicado. Você pode resolver isso return false;no final do manipulador, mas se você tiver outros manipuladores que precisam ser executados posteriormente, e interromper a propagação não é uma opção, isso se torna um problema.
Wd_in
67

eu prefiro

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

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

sobre

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

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

Principalmente porque torna o HTML mais legível. Na verdade, acho que meu primeiro exemplo é mais fácil de estilizar com CSS, pois o CSS funciona muito bem com elementos aninhados.

Mas é uma questão de gosto, suponho.


Se você precisar de mais opções de estilo, adicione uma tag de extensão.

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

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

Código ainda parece melhor na minha opinião.

Znarkus
fonte
3
Incluir a entrada dentro do rótulo é o mesmo que usar HTML para o layout.
Emil
8
Eu gosto desta solução também para casos como este: <label>Expires after <input name="exp" /> days</label>(etiqueta é antes e depois do elemento de entrada)
Philipp
Acho que o último exemplo é - além dos atributos for e id - não é realmente diferente de ter o rótulo ao lado da entrada e ambos agrupados em um div, liou o que não é !?
Retrovertigo 30/05
1
@retrovertigo - funcionalmente? Não. Ele apenas reduz a marcação e reduz o uso semântico de termos. Sabemos que a entrada firstnamedeve seguir o rótulo para firstname, mas os navegadores precisam da declaração. É tudo uma questão de gosto e o que VOCÊ acha melhor (e mais fácil de depurar) no seu código. Eu prefiro usar aninhado agora, apesar de demorar um pouco para eu me acostumar.
Xhynk 28/07
3
@ MPavlak - uma rápida olhada e encontrei essa orientação no site w3.org. w3.org/WAI/tutorials/forms/labels . Em seguida, verifiquei w3.org/TR/WCAG20-TECHS/H44.html . Na parte inferior (é obscura), diz que, para reivindicar conformidade, você precisa passar nos critérios de teste, e que especifica especificamente que você deve usar o atributo for. Na realidade, quando testei isso pela última vez no Apple Voiceover (10% de leitores de tela de área de trabalho, 60% de parte de dispositivos móveis) as etiquetas implícitas não funcionavam, então esse foi outro fator importante. Espero que ajude!
James Westgate
39

Se você incluir a tag de entrada na tag label, não precisará usar o atributo 'for'.

Dito isso, não gosto de incluir a tag de entrada nos meus rótulos porque acho que eles são entidades separadas, não contendo.

Terry
fonte
8
O para requer que você use um id embora, o que torna estruturação do layout hierarquicamente muito difícil :-(
lethalman
39

Diferença de comportamento: clicar no espaço entre o rótulo e a entrada

Se você clicar no espaço entre o rótulo e a entrada, ele ativará a entrada apenas se o rótulo contiver a entrada.

Isso faz sentido, pois nesse caso o espaço é apenas outro caractere do rótulo.

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

Ser capaz de clicar entre o rótulo e a caixa significa que é:

  • mais fácil clicar
  • menos claro onde as coisas começam e terminam

Os exemplos da caixa de seleção Bootstrap v3.3 usam a entrada interna: http://getbootstrap.com/css/#forms Pode ser sábio segui-los. Mas eles mudaram de idéia na v4.0 https://getbootstrap.com/docs/4.0/components/forms/#checkboxes-and-radios, então não sei mais o que é sábio:

As caixas de seleção e o uso de rádios são criados para oferecer suporte à validação de formulário baseada em HTML e fornecer rótulos concisos e acessíveis. Como tal, os nossos <input>s e <label>s são elementos irmãos, em oposição a um <input>dentro de um <label>. Isso é um pouco mais detalhado, pois você deve especificar o id e os atributos para relacionar o <input>e <label>.

Pergunta do UX que discute esse ponto em detalhes: /ux/23552/should-the-space-between-the-checkbox-and-label-be-clickable

Ciro Santilli adicionou uma nova foto
fonte
Esta não é uma diferença de especificação. A alternância funciona nos dois casos em todos os navegadores compatíveis.
hexalys
@hexalys Obrigado pelo relatório. Eu atualizei a resposta. Você quer dizer que os navegadores compatíveis devem alternar ou não nos dois casos? Se você pudesse criar um link para a passagem padrão relevante, isso seria incrível.
Ciro Santilli escreveu:
1
Sim. Embora eu não tenha notado que seu exemplo é enganoso, porque seu espaço não é realmente um espaço de texto . É uma margindas caixas de seleção. O comportamento do Firefox no seu exemplo é peculiar e parece um bug. A labelconterá os espaços ou preenchimentos em torno do conteúdo embutido, conforme clicável. Porém, como o modelo de conteúdo de um rótulo é um conteúdo embutido / de frases, a margem de entrada não deve ser clicável, a menos que seu rótulo seja criado. Nessedisplay: block caso, o interior do rótulo blockse torna clicável em todos os navegadores.
Hexalys 26/12/14
1
Observe que o link Bootstrap na resposta vai para os documentos da v3.3. Os documentos da v4.0 parecem indicar que eles mudaram de idéia: "O uso de caixas de seleção e rádios é criado para oferecer suporte à validação de formulário baseada em HTML e fornecer rótulos concisos e acessíveis. Assim, nossos <input> se <label> s são elementos irmãos em oposição a uma <entrada> dentro de um <rótulo>. Isso é um pouco mais detalhado, pois você deve especificar o id e os atributos para relacionar o <entrada> e <rótulo> ".
Michael Krebs
2
Essa diferença de comportamento é grande para mim. Quando os elementos são irmãos, qualquer margem em qualquer elemento reduz a área de superfície clicável que acionará o elemento de entrada. Aninhar a entrada dentro da etiqueta preserva a área máxima clicável, oferecendo acessibilidade máxima mesmo para usuários que lutam com movimentos precisos do mouse ou toque. No Bootstrap 4, o aninhamento ainda funciona e ainda exibe o mesmo sem a necessidade de ajustar ou substituir qualquer CSS do Bootstrap.
Turgs
17

Pessoalmente, gosto de manter o rótulo do lado de fora, como no seu segundo exemplo. É por isso que o atributo FOR está lá. A razão é que frequentemente aplicarei estilos ao rótulo, como uma largura, para que o formulário fique bonito (abreviado abaixo):

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

Faz com que eu possa evitar tabelas e todo esse lixo nos meus formulários.

Papagaios
fonte
3
Você não deve deixar a apresentação em CSS, em vez de usar <br />para separar as entradas?
Znarkus 11/09/11
1
@ Znarkus - sim, normalmente envolvo-os em OL / LIs para lidar com formatação assim, esse foi apenas um exemplo rápido e abreviado.
Papagaios
1
@ Cenouras: Isso não faz muito sentido semanticamente, imo. E se você precisar embrulhá-los, por que não envolvê-los com o rótulo?
Znarkus 11/09/11
1
@Parrots Com esse raciocínio, acho que tudo em uma página deve entrar em ul / li. E <label> <span>My text</span> <input /> </label>você tem todas as opções de estilo que você (sempre) precisará.
Znarkus 13/09/11
1
O uso de "for" obriga a usar um ID, o que é ruim para layouts hierárquicos.
Lethalman
15

Consulte http://www.w3.org/TR/html401/interact/forms.html#h-17.9 para obter as recomendações do W3.

Eles dizem que isso pode ser feito de qualquer maneira. Eles descrevem os dois métodos como explícitos (usando "for" com o ID do elemento) e implícitos (incorporando o elemento no rótulo):

Explícito:

O atributo for associa um rótulo a outro controle explicitamente: o valor do atributo for deve ser o mesmo que o valor do atributo id do elemento de controle associado.

Implícito:

Para associar um rótulo a outro controle implicitamente, o elemento de controle deve estar dentro do conteúdo do elemento LABEL. Nesse caso, o LABEL pode conter apenas um elemento de controle.

user470514
fonte
Acabei de descobrir que o implícito não está funcionando no IE ... .quantas idéias?
Carllynchin
11

Ambos estão corretos, mas colocar a entrada dentro do rótulo torna muito menos flexível ao estilizar com CSS.

Primeiro, a <label>é restrito em quais elementos ele pode conter . Por exemplo, você só pode colocar um <div>entre o <input>texto e o rótulo, se <input>não estiver dentro do <label>.

Segundo, embora existam soluções alternativas para facilitar o estilo, como agrupar o texto do rótulo interno com uma extensão, alguns estilos serão herdados dos elementos pai, o que pode tornar o estilo mais complicado.

nicholaides
fonte
muito menos flexível? Você pode elaborar? como outros já mencionaram, você pode simplesmente agrupar o texto do rótulo interno com uma extensão, a menos que seja isso que o torne muito menos flexível?
MPVlak
7

Uma 'pegadinha' notável determina que você nunca deve incluir mais de um elemento de entrada dentro de um elemento <label> com um atributo "for" explícito, por exemplo:

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

Embora isso possa ser tentador para recursos de formulário nos quais um valor de texto personalizado é secundário a um botão de opção ou caixa de seleção, a funcionalidade de foco no clique do elemento label lança imediatamente o foco no elemento cujo ID está explicitamente definido no atributo 'for' , tornando quase impossível para o usuário clicar no campo de texto contido para inserir um valor.

Pessoalmente, tento evitar elementos de rótulo com filhos de entrada. Parece semanticamente impróprio para um elemento de rótulo abranger mais do que o próprio rótulo. Se você estiver aninhando entradas em rótulos para obter uma certa estética, você deve usar CSS.

Aaron
fonte
4
Este não é um "pegadinha". É explicitamente parte da especificação; o rótulo pode conter até 1 controle nele. Você também está misturando os estilos implícito e explícito aqui - se você colocar o controle dentro do rótulo, não precisará for... e se quiser usar for, ter o controle dentro do rótulo não faz muito sentido .
Chao
É verdade, mas parece que essa especificação não é bem compreendida. Corremos esse problema com a API de formulários do Drupal 6, que gerou uma marcação que criou um cenário não muito diferente do descrito acima. Meu colega e eu coçamos a cabeça por um minuto ou dois, então pensei em expor a questão aqui para evitar possíveis confusões no futuro.
Aaron
não há necessidade de "for" no cenário label-> input. uma entrada por rótulo e tem o benefício de não precisar saber o nome ou o ID, e você pode criar um bom estilo de css para manter as coisas encapsuladas, além de ter o foco quando um outro elemento é clicado. consulte zipstory.com/signup, por exemplo, sobre uma maneira limpa de fazer isso.
Jason Sebring
Obrigado; isso respondeu a outra pergunta relacionada que eu tinha, a saber, se ela tem potencialmente mais de uma entrada dentro de um rótulo. (Contexto: várias opções de botão de opção, uma por linha, cada entrada de botão de opção possui 1, 2, 3 ou possivelmente mais entradas do tipo texto, com a intenção de clicar em uma linha que resulta da seleção do botão de opção dessa linha, se não selecionado e permitindo a edição das entradas / entradas nessa linha.) Isso deixa a porta aberta para o fato de haver vários rótulos para texto sem entrada no formulário, mas respondeu à minha pergunta sobre se o que eu pensava era bom. (Não era.)
Christos Hayward
6

Como a maioria das pessoas disse, os dois lados funcionam de fato, mas acho que apenas o primeiro deveria. Sendo semanticamente rígido, o rótulo não "contém" a entrada. Na minha opinião, o relacionamento de contenção (pai / filho) na estrutura de marcação deve refletir a contenção na saída visual . ou seja, um elemento ao redor de outro na marcação deve ser desenhado ao redor do elemento no navegador . De acordo com isso, o rótulo deve ser o irmão da entrada, não o pai. Portanto, a opção número dois é arbitrária e confusa. Todo mundo que leu o Zen do Python provavelmente concordará (Flat é melhor que aninhado, Sparse é melhor que denso; deve haver um - e de preferência apenas um - meio óbvio de fazê-lo ...).

Devido a decisões como essa do W3C e dos principais fornecedores de navegadores (permitindo "da maneira que você preferir", em vez de "fazer da maneira certa"), a Web está tão bagunçada hoje e os desenvolvedores precisam lidar com problemas e código legado tão diverso.

slashCoder
fonte
5

Eu costumo ir com as duas primeiras opções. Vi um cenário em que a terceira opção foi usada, quando as opções de rádio estavam incorporadas nos rótulos e no css continha algo como

label input {
    vertical-align: bottom;
}

para garantir o alinhamento vertical adequado dos rádios.

Victor Ionescu
fonte
2

Eu prefiro agrupar elementos dentro do meu <label>porque não preciso gerar os IDs.

Sou desenvolvedor de Javascript e React ou Angular são usados ​​para gerar componentes que podem ser reutilizados por mim ou por outras pessoas. Seria fácil duplicar um ID na página, levando a comportamentos estranhos.

Nicolas Zozol
fonte
1

Uma coisa que você precisa considerar é a interação da caixa de seleção e das entradas de rádio com o javascript.

Usando a estrutura abaixo:

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

Quando o usuário clica na função controlCheckbox () "Texto do rótulo", é acionada uma vez.

Mas quando a tag de entrada é clicada, a função controlCheckbox () pode ser acionada duas vezes em alguns navegadores mais antigos. Isso ocorre porque as tags de entrada e rótulo acionam o evento onclick anexado à caixa de seleção.

Então você pode ter alguns erros em seu checkboxState.

Ultimamente, tenho encontrado esse problema no IE11. Não tenho certeza se os navegadores modernos têm problemas com essa estrutura.

Mariusz
fonte
-1

A principal vantagem de colocar inputdentro labelé a eficiência de digitação para humanos e armazenamento de bytes para computadores.

@Znarkus disse em seu comentário ao OP,

Um dos grandes profissionais de colocar o <input />interior de <label>, é que você pode omitir fore id: <label>My text <input /></label>no seu exemplo. Muito melhor!

Nota: No código @Znarknus, outra eficiência foi incluída, não explicitamente declarada no comentário. type="text"também pode ser omitido e inputrenderizará uma caixa de texto por padrão.

Uma comparação lado a lado de pressionamentos de tecla e bytes [1].

31 pressionamentos de tecla, 31 bytes

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

58 pressionamentos de tecla, 58 bytes

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

Caso contrário, os trechos são visualmente iguais e oferecem o mesmo nível de acessibilidade do usuário. Um usuário pode clicar ou tocar no rótulo para colocar o cursor na caixa de texto.

[1] Arquivos de texto (.txt) criados no bloco de notas no Windows, bytes das propriedades do Windows File Explorer

ThisClark
fonte