O indicador de foco (geralmente indicado por um "anel de foco") identifica o elemento em foco na página. Para usuários que não conseguem usar um mouse, esse indicador é extremamente importante, porque funciona como um substituto do ponteiro do mouse.
Se o indicador de foco padrão do navegador conflitar com seu design, use CSS para estilizá-lo. Não se esqueça de pensar nos usuários de teclado.
Use :focus
para sempre mostrar um indicador de foco
A pseudoclasse :focus
é aplicada sempre que um elemento recebe o foco, independentemente do dispositivo
de entrada (mouse, teclado, stylus etc.) ou do método usado para dar foco. Por exemplo,
o <div>
abaixo tem um tabindex
que permite o foco. Ele também tem um
estilo personalizado para o estado :focus
:
div[tabindex="0"]:focus {
outline: 4px dashed orange;
}
Não importa se você usa um mouse para clicar ou um teclado para navegar,
o <div>
sempre vai ter a mesma aparência.
Infelizmente, os navegadores podem ser inconsistentes na forma como aplicam o foco. A possibilidade de um elemento receber o foco pode depender do navegador e do sistema operacional.
Por exemplo, o <button>
abaixo também tem um estilo personalizado para o estado
:focus
.
button:focus {
outline: 4px dashed orange;
}
Se você clicar no <button>
com um mouse no Chrome no macOS, vai aparecer
o estilo de foco personalizado. No entanto, o estilo de foco personalizado não será mostrado se você
clicar em <button>
no Safari no macOS. Isso ocorre porque, no
Safari, o elemento não recebe foco quando você clica nele.
Como o comportamento de foco é inconsistente, pode ser necessário testar em diferentes dispositivos para garantir que os estilos de foco sejam aceitáveis para os usuários.
Usar :focus-visible
para mostrar seletivamente um indicador de foco
A nova
pseudoclasse :focus-visible
é aplicada sempre que um elemento recebe o foco e o
navegador determina, por meio de heurísticas, que mostrar um indicador de foco seria
benéfico para o usuário. Em particular, se a interação mais recente do usuário
foi pelo teclado e a tecla pressionada não incluiu uma meta, ALT
/ OPTION
ou CONTROL
, então :focus-visible
vai corresponder.
O botão no exemplo abaixo seletivamente mostra um indicador de foco. Se você usar um mouse para clicar nele, os resultados serão diferentes do que se você usar um teclado para selecioná-lo.
button:focus-visible {
outline: 4px dashed orange;
}
Usar :focus-within
para estilizar o elemento pai de um elemento em foco
A
pseudoclasse
:focus-within
é aplicada a um elemento quando ele recebe
foco ou quando outro elemento dentro dele recebe foco.
Ele pode ser usado para destacar uma região da página e chamar a atenção do usuário para essa área. Por exemplo, o formulário abaixo recebe foco quando o formulário é selecionado e também quando qualquer um dos botões de opção é selecionado.
form:focus-within {
background: #ffecb3;
}
Quando mostrar um indicador de foco
Uma boa regra geral é se perguntar: "Se você clicar nesse controle enquanto usa um dispositivo móvel, ele vai mostrar um teclado?"
Se a resposta for "sim", o controle provavelmente sempre vai mostrar um indicador
de foco, independentemente do dispositivo de entrada usado para dar foco. Um bom exemplo é
o elemento <input type="text">
. O usuário precisa enviar a entrada para o
elemento pelo teclado, independentemente de como o elemento de entrada recebeu o foco
originalmente. Portanto, é útil sempre mostrar um indicador de foco.
Se a resposta for "não", o controle poderá mostrar seletivamente um indicador
de foco. Um bom exemplo é o elemento <button>
. Se um usuário clicar nele com
um mouse ou tela touchscreen, a ação será concluída, e um indicador de foco pode não
ser necessário. No entanto, se o usuário estiver navegando com um teclado, será útil
mostrar um indicador de foco para que o usuário possa decidir se quer ou não
clicar no controle usando as teclas ENTER
ou SPACE
.
Evite outline: none
A maneira como os navegadores decidem quando desenhar um indicador de foco é, francamente, muito
confusa. Mudar a aparência de um elemento <button>
com CSS ou atribuir
a um elemento um tabindex
fará com que o comportamento padrão do anel de foco do navegador
seja iniciado.
Um antipadrão muito comum é remover o indicador de foco usando CSS, como:
/* Don't do this!!! */
:focus {
outline: none;
}
Uma maneira melhor de contornar esse problema é usar uma combinação de :focus
e
o polyfill :focus-visible
. O primeiro bloco de código abaixo demonstra como
o polyfill funciona, e o app de exemplo abaixo fornece um exemplo de uso
do polyfill para mudar o indicador de foco em um botão.
/*
This will hide the focus indicator if the element receives focus via the
mouse, but it will still show up on keyboard focus.
*/
.js-focus-visible :focus:not(.focus-visible) {
outline: none;
}
/*
Optionally: Define a strong focus indicator for keyboard focus.
If you choose to skip this step, then the browser's default focus
indicator will be displayed instead.
*/
.js-focus-visible .focus-visible {
…
}