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 selecionados com a tecla Tab fazem parte da ordem de navegação sequencial do documento. Outros elementos são inertes, ou seja, não são interativos. Com atributos HTML, é possível tornar elementos interativos inertes e elementos inertes interativos.

Por padrão, a ordem de foco da navegação é a mesma da ordem visual, que é a ordem do código-fonte. Há atributos HTML que podem alterar essa ordem e propriedades CSS que podem mudar 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 demonstram os dois exemplos a seguir, as ordens de tabulação que diferem da ordem visualmente esperada confundem os usuários e prejudicam a experiência.

Neste exemplo, o valor do atributo tabindex 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 declaração flex-flow: row-reverse; inverteu a ordem visual. Além disso, a propriedade order do CSS 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, criando uma desconexão para usuários de teclado.

Tornar elementos inertes interativos

Os atributos contenteditable e tabindex, sendo globais, podem ser adicionados a qualquer elemento, tornando-os focáveis no processo. Os elementos focalizáveis também podem ser focalizados com um mouse ou ponteiro, definindo o atributo autofocus 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 poderiam receber foco o recebam, geralmente com a tecla Tab, por isso o nome.

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

Nesta página, o botão de compartilhamento, <share-action>, é um elemento personalizado. O tabindex="0" adiciona esse elemento que normalmente não é focalizável à 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>

Há outro elemento personalizado nesta página: 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 navegável com a tecla Tab. O elemento pode receber foco, como usando HTMLElement.focus(), mas não faz parte da ordem de navegação por foco sequencial. A convenção para elementos não tabuláveis e focalizáveis é usar tabindex="-1". Se você adicionar tabindex="-1" a um elemento interativo, ele não poderá mais ser selecionado com a tecla Tab.

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

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

Elementos com um tabindex de 1 ou maior são incluídos em uma sequência de guias separada. Como você vai notar no Codepen, o uso da tecla Tab começa em uma sequência separada, em ordem do menor para o maior valor, antes de passar pelos valores na sequência regular (nenhum tabindex definido ou tabindex="0") na ordem de origem:

tabindex com um valor positivo coloca o elemento em uma sequência de foco prioritária, o que pode levar ao caos na ordem de foco. Evite modificar a ordem do DOM com tabindex. Além de criar experiências ruins para o usuário, as ordens de tabulação alteradas são difíceis de gerenciar e manter para os desenvolvedores.

O atributo contenteditable

O atributo contenteditable foi discutido anteriormente. Definir contenteditable="true" em qualquer elemento o torna editável, focável e parte da ordem de tabulação. O comportamento de foco é semelhante a definir tabindex="0", mas não é igual. Elementos contenteditable aninhados são focalizáveis, mas não podem ser selecionados 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 por foco.

Atribuir 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 atributos autofocus recebe o 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. Definir autofocus em um controle de formulário significa que ele aparece ao rolar a página. Todos os usuários, incluindo aqueles que usam leitores de tela e aqueles com pequenas janelas de visualização, podem não "ver" as instruções do formulário, talvez até rolando além do rótulo normalmente visível do controle do formulário. O atributo autofocus não altera a ordem de navegação sequencial por foco do documento. Os elementos na sequência que vêm antes do elemento com foco automático são ignorados. Por esses motivos, não é recomendável incluir o atributo autofocus.

A exceção à recomendação "não use autofocus" é incluir o atributo autofocus em elementos <dialog>. Quando uma caixa de diálogo é aberta, o navegador se concentra automaticamente no primeiro elemento interativo focalizável dentro do <dialog>. Isso 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 o foco quando ela 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 botão de fechar <button> permite que ele receba o foco quando a caixa de diálogo é aberta. Como o primeiro elemento na caixa de diálogo, ele teria recebido o foco de qualquer maneira. Por padrão, quando uma caixa de diálogo é aberta, o primeiro elemento focável dentro dela recebe o foco, a menos que um elemento diferente 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 a controles de formulário compatíveis e adicionar o atributo global inert a um contêiner faz com que os elementos não possam ser acessados com a tecla Tab. Esses três atributos NÃO são intercambiáveis.

Valor tabindex negativo

Um atributo tabindex com um valor negativo torna um elemento focalizável, mas não navegável com a tecla Tab. Ao adicionar tabindex="0" a um elemento que pode ser focado 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 tabuláveis da ordem de navegação de foco sequencial.

Um valor tabindex negativo impede que os usuários do 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 disabled faz com que os controles de formulário em que ele é aplicado e os descendentes deles, se houver, não possam ser focados. Controles de formulário desativados não podem ser focados, não recebem eventos de clique e não são enviados com o formulário.

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

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

Como é um atributo booleano, a presença dele desativa o elemento que, de outra forma, estaria ativado. Não é possível definir como false. Para reativar um elemento desativado, o atributo precisa ser removido, geralmente com Element.removeAttribute('disabled').

A propriedade HTMLInputElement.disabled permite verificar se uma entrada está desativada. Como disabled não é um atributo global, ele não é herdado do HTMLElement, mas todas as interfaces de elementos compatíveis, como HTMLSelectElement, HTMLTextareaElement, têm a mesma propriedade somente leitura.

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

O atributo inert

Quando o atributo booleano global inert é adicionado a um elemento, ele e todo o conteúdo aninhado são desativados, o que significa que não é possível clicar ou navegar 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 oculto.

Ao aplicar disabled a controles de formulário, o navegador fornece um estilo padrão que pode ser estilizado usando a pseudoclasse :disabled. 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 resultar em uma experiência ruim para o usuário. Como o conteúdo inerte não está disponível para usuários de leitores de tela, isso pode causar confusão quando usuários com visão veem 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 muda para conteúdo não visível. Qualquer coisa renderizada fora da tela que não apareça automaticamente quando focada deve ser tornada inerte. Se o conteúdo estiver oculto, mas aparecer quando estiver em foco, como um link para pular para o conteúdo, ele não precisa ser tornado inerte.

Teste seu conhecimento

Teste seus conhecimentos sobre foco.

Se um elemento não puder ser focado, 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 poderá ser focado.
Correto.
Ela não será exibida.
Tente novamente.
Se for um elemento de formulário, ele não será enviado.
Correto.