Foco

Os elementos interativos, incluindo controles de formulário, links, e botões, são focalizáveis e podem ser acessados com a tecla Tab por padrão. Os elementos que podem ser acessados com a tecla Tab fazem parte da ordem de navegação sequencial de foco do documento. Outros elementos são inertes, ou seja, não são interativos. Com os atributos HTML, é possível tornar elementos interativos inertes e elementos inertes interativos.

Por padrão, o foco da navegação é a mesma que a ordem visual, que é a ordem do código-fonte. Há atributos HTML que podem alterar essa ordem e propriedades CSS que podem alterar a ordem visual do conteúdo. Mudar a ordem de tabulação com HTML ou a ordem de renderização visual com CSS pode prejudicar a experiência do usuário.

Não altere a ordem de tabulação percebida e real com CSS e HTML. Como os dois exemplos a seguir demonstram, as ordens de tabulação que diferem da ordem visualmente esperada são confusas para os usuários e ruins para a experiência do usuário.

No exemplo a seguir, o valor do tabindex atributo tornou a ordem de tabulação caótica:

Neste exemplo, o CSS criou uma divergência entre a ordem de tabulação e a ordem visual do conteúdo:

A flex-flow: row-reverse; declaração inverteu a ordem visual. Além disso, a propriedade de ordem CSS order foi aplicada à sexta palavra, "This", que moveu visualmente essa palavra. A sequência de tabulação é a ordem do código, que não corresponde mais à ordem visual. Isso cria uma desconexão para usuários de teclado.

Alguns recursos de CSS, incluindo flexbox, grade, posicionamento, transformações, e várias colunas, podem alterar a ordem visual do conteúdo. Teste o conteúdo com a tecla Tab com um teclado: use shift + tab para voltar pelo conteúdo. Use CSS para indicar qual elemento está em foco. Não reordene elementos focalizáveis com CSS.

É importante manter uma ordem de tabulação lógica em todos os tamanhos de janela de visualização.

Tornar elementos inertes interativos

Os atributos contenteditable e tabindex, sendo atributos globais, podem ser adicionados a qualquer elemento, tornando-os focalizáveis no processo. Os elementos focalizáveis também podem ser focalizados com um mouse ou ponteiro, definindo o autofocus atributo ou por script, como com element.focus().

O atributo tabindex

O atributo global tabindex , introduzido em atributos, permite que elementos que, de outra forma, não seriam capazes de receber foco, geralmente com Tab, recebam foco, daí o nome.

O atributo tabindex usa um número inteiro como valor. Um valor negativo torna um elemento focalizável, mas não pode ser acessado com a tecla Tab. Um valor tabindex de 0 torna o elemento focalizável e pode ser acessado com a tecla Tab, adicionando o elemento em que ele é aplicado à ordem de navegação sequencial de foco na ordem do código-fonte. Um valor de 1 ou maior torna o elemento focalizável e pode ser acessado com a tecla Tab, mas o adiciona a uma sequência de tabulação priorizada e deve ser evitado.

Nesta página, o botão de compartilhamento, <share-action>, é um elemento personalizado. O tabindex="0" adiciona esse elemento à ordem de tabulação padrão do teclado:

<share-action authors="@front-end.social/@estellevw" data-action="click"
  data-category="web.dev" data-icon="share" data-label="share, mastodon"
  role="button" tabindex="0">
  <svg aria-label="share" role="img" xmlns="http://www.w3.org/2000/svg">
    <use href="#shareIcon" />
  </svg>
  <span>Share</span>
</share-action>

Além disso, a navegação local tem um elemento personalizado com um valor tabindex negativo:

<web-navigation-drawer type="standard" tabindex="-1">

Um atributo tabindex com um valor negativo torna o elemento focalizável, mas não pode ser acessado com a tecla Tab. O elemento pode receber foco, como usar HTMLElement.focus(), mas não faz parte da ordem de navegação sequencial de foco. A convenção para elementos focalizáveis que não podem ser acessados com a tecla Tab é usar tabindex="-1". Se você adicionar tabindex="-1" a um elemento interativo, ele não poderá mais ser acessado com a tecla Tab.

O element.focus() método pode ser usado para definir o foco em elementos focalizáveis. Os navegadores rolam elementos focados para a visualização. Por esse motivo, evite o uso de element.focus({preventScroll:true}), já que focar em um elemento não visível é uma experiência ruim do usuário.

Se você quiser consultar o documento para descobrir qual elemento está em foco, use a propriedade somente leitura Document.activeElement.

Os elementos com um tabindex de 1 ou maior são incluídos em uma sequência de guias separada. Como no Codepen a seguir, a tabulação começa em uma sequência separada, em ordem do menor para o maior valor, antes de passar por aqueles na sequência normal (nenhum tabindex definido ou tabindex="0") na ordem de origem:

tabindex com um valor positivo coloca o elemento em uma sequência de foco priorizada, o que pode levar ao caos na ordem de foco. Evite modificar a ordem do DOM com tabindex. A ordem de tabulação alterada pode criar experiências ruins do usuário e é difícil de manter.

O atributo contenteditable

O atributo contenteditable foi discutido anteriormente. Definir contenteditable="true" em qualquer elemento o torna editável, focalizável e parte da ordem de tabulação. O comportamento de foco é semelhante a definir tabindex="0", mas não é o mesmo. Os elementos contenteditable aninhados são focalizáveis, mas não podem ser acessados com a tecla Tab. Para tornar um elemento contenteditable aninhado acessível com a tecla Tab, adicione tabindex="0", que o adiciona à ordem de navegação sequencial de foco.

Dar autofocus a elementos interativos

Embora o booleano autofocus seja um atributo global que pode ser definido em qualquer elemento, ele não torna um elemento inerte interativo. Quando a página é carregada, o primeiro elemento focalizável com os autofocus atributos recebe foco, desde que esse elemento seja exibido e não esteja aninhado em um <dialog>.

Definir o foco automaticamente no conteúdo pode ser confuso para os usuários. Quando você define autofocus em um controle de formulário, esse controle de formulário é rolado para a visualização no carregamento da página. Seus usuários, incluindo usuários de leitores de tela e usuários com janelas de visualização pequenas, podem perder as instruções do formulário ou até mesmo o rótulo do controle de formulário. Além disso, o atributo autofocus não altera a ordem de navegação sequencial de foco do documento. Os elementos na sequência que vêm antes do elemento com foco automático são ignorados. Por esses motivos, evite usar o atributo autofocus.

A exceção à recomendação "não use autofocus" é incluir o autofocus atributo em <dialog> elementos. Quando uma caixa de diálogo é aberta, o navegador se concentra automaticamente no primeiro elemento interativo focalizável na <dialog>, o que significa que não é necessário adicionar autofocus a um elemento. Se você quiser garantir que um elemento interativo específico na caixa de diálogo receba foco quando a caixa de diálogo for aberta, adicione o atributo autofocus a esse elemento.

<dialog open>
  <form method="dialog">
    <button type="submit" autofocus>close</button>
  </form>
</dialog>

O atributo autofocus definido no <button> de fechamento permite que ele receba foco quando a caixa de diálogo for aberta. Como o primeiro elemento na caixa de diálogo, ele teria recebido foco em qualquer caso. Por padrão, quando uma caixa de diálogo é aberta, o primeiro elemento focalizável na caixa de diálogo recebe foco, a menos que um elemento diferente na caixa de diálogo tenha o atributo autofocus definido.

Tornar elementos interativos inertes

Há também atributos HTML que podem remover elementos interativos da sequência de tabulação. Incluir um tabindex negativo em elementos focalizáveis, adicionar o atributo disabled aos controles de formulário de suporte e adicionar o atributo global inert a um contêiner tornam os elementos não acessíveis com a tecla Tab. Esses três atributos são completamente separados e não são intercambiáveis.

Valor tabindex negativo

Um atributo tabindex com um valor negativo torna um elemento focalizável, mas não pode ser acessado com a tecla Tab. Embora não seja necessário adicionar tabindex="0" a um elemento focalizável por padrão, incluindo links, botões, controles de formulário e elementos que são contenteditable não é necessário; incluir um tabindex com um valor negativo remove elementos normalmente acessíveis com a tecla Tab da ordem de navegação sequencial de foco.

Um valor tabindex negativo impede que os usuários de teclado se concentrem em elementos interativos, mas não desativa o elemento. Os usuários de ponteiro ainda podem se concentrar no elemento. Para desativar um elemento, use o atributo disabled.

Desativado

O atributo booleano desativado torna os controles de formulário em que ele é aplicado e seus descendentes, se houver, não focalizáveis. Os controles de formulário desativados não podem ser focalizados, não recebem eventos de clique e não são enviados após o envio do formulário.

disabled não é um atributo global. Ele se aplica a <button>, <input>, <optgroup>, <option>, <select>, <textarea>, elementos personalizados associados a formulários e <fieldset>. Quando definido em <optgroup> ou <fieldset>, todos os controles de formulário filhos são desativados, exceto o conteúdo da primeira <legend> do <fieldset>.

Os mesmos elementos que oferecem suporte a disabled também podem ser segmentados com as :disabled e :enabled pseudoclasses. Os elementos desativados com o disabled atributo são geralmente estilizados como cinza claro com a folha de estilo do user-agent, mesmo que uma accent-color esteja definida.

Como é um atributo booleano, a presença do atributo desativa o elemento ativado; não é possível defini-lo como false. Para reativar um elemento desativado, o atributo precisa ser removido, geralmente com Element.removeAttribute('disabled').

A HTMLInputElement.disabled propriedade permite verificar se uma entrada está desativada. Como disabled não é um atributo global, ele não é herdado do HTMLElement, mas cada interface de elemento de suporte, como HTMLSelectElement, HTMLTextareaElement, tem a mesma propriedade somente leitura.

O atributo disabled não se aplica a elementos inert normalmente que são focalizáveis com tabindex ou contenteditable, nem ao elemento <form>. Para desativar esses elementos, o atributo global inert pode ser usado.

O atributo inert

Quando o atributo booleano global inert é adicionado a um elemento, esse elemento e todo o conteúdo aninhado são desativados, o que significa que não é possível clicar ou acessar com a tecla Tab. Eles também são removidos da árvore de acessibilidade. Embora inert possa ser aplicado a qualquer elemento, ele geralmente é usado para seções de conteúdo, como conteúdo fora da tela ou conteúdo oculto.

Ao aplicar disabled aos controles de formulário, o navegador fornece um estilo padrão e pode ser estilizado usando a :disabled pseudoclasse. O atributo inert não fornece indicadores visuais e não tem uma pseudoclasse correspondente (embora o [inert] seletor de atributo corresponda).

Usar inert em conteúdo visível sem estilos que indiquem a inércia pode levar a uma experiência ruim do usuário. Como o conteúdo inerte não está disponível para usuários de leitores de tela, isso pode levar à confusão quando os usuários de leitores de tela com visão enxergam conteúdo na tela que não está disponível para as ferramentas de acessibilidade. Deixe a inércia muito aparente com CSS.

Verifique se o foco nunca se move para conteúdo não visível. Qualquer coisa renderizada fora da tela que não apareça automaticamente quando focada precisa ser tornada inerte. Se o conteúdo estiver oculto mas aparecer quando focado, como um link para pular para o conteúdo, ele não precisará ser tornado inerte.

Teste seu conhecimento

Teste seu conhecimento sobre foco.

Se um elemento não puder ser focalizado, ele será descrito como o quê?

Empty.
Tente novamente.
Inerte.
Correto.
Oculto.
Tente novamente.

O que será verdadeiro se o elemento tiver um atributo disabled?

Ele não será focalizável.
Correto.
Ele não será exibido.
Tente novamente.
Se for um elemento de formulário, ele não será enviado.
Correto.