O indicador de foco (geralmente representado por um "anel de foco") identifica o elemento que está em foco na página. Para usuários que não conseguem usar um mouse, esse indicador é extremamente importante porque funciona como substituto do cursor do mouse.
Se o indicador de foco padrão do navegador entrar em conflito com o design, use o CSS para mudar o estilo. Lembre-se apenas de pensar nos usuários do teclado.
Use :focus
para sempre mostrar um indicador de foco
A pseudoclasse :focus
é aplicada sempre que um elemento está em foco, independente do dispositivo
de entrada (mouse, teclado, stylus etc.) ou do método usado para focalizar um elemento. Por exemplo,
a <div>
abaixo tem um tabindex
que a torna focalizável. Ela também tem um
estilo personalizado para o estado :focus
:
div[tabindex="0"]:focus {
outline: 4px dashed orange;
}
Independentemente de você usar um mouse para clicar nele ou um teclado para navegar até ele,
a <div>
sempre terá a mesma aparência.
Infelizmente, os navegadores podem ser inconsistentes com a forma como eles aplicam o foco. O recebimento ou não de um elemento depende do navegador e do sistema operacional.
Por exemplo, a <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 encontrar
o estilo de foco personalizado. No entanto, você não verá o estilo de foco personalizado se
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 do foco é inconsistente, pode ser necessário fazer alguns testes em dispositivos diferentes para garantir que os estilos de foco sejam aceitáveis para os usuários.
Use :focus-visible
para mostrar um indicador de foco de forma seletiva
A nova pseudoclasse
:focus-visible
é aplicada sempre que um elemento recebe foco e o
navegador determina por heurística que mostrar um indicador de foco seria
benéfico para o usuário. Especificamente, se a interação mais recente do usuário
foi pelo teclado e o pressionamento de tecla não incluiu uma tecla meta, ALT
/ OPTION
ou CONTROL
, :focus-visible
vai corresponder.
O botão no exemplo abaixo mostra seletivamente um indicador de foco. Se você usar um mouse para clicar nele, os resultados serão diferentes do que se você usasse um teclado para acessar a tecla Tab.
button:focus-visible {
outline: 4px dashed orange;
}
Usar :focus-within
para definir o estilo do pai de um elemento em foco
A
pseudoclasse
:focus-within
é aplicada a um elemento quando ele recebe
foco ou quando outro elemento dentro desse elemento recebe foco.
Ele pode ser usado para destacar uma região da página e chamar a atenção do usuário para ela. Por exemplo, o formulário abaixo recebe foco quando ele é 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 prática é perguntar a si mesmo: "Se você clicasse nesse controle enquanto usa um dispositivo móvel, esperaria que ele exibisse um teclado?"
Se a resposta for "sim", o controle provavelmente sempre mostrará um indicador
de foco, independentemente do dispositivo de entrada usado para focalizá-lo. Um bom exemplo é
o elemento <input type="text">
. O usuário precisará enviar entrada para o
elemento usando o teclado, independentemente de como o elemento de entrada recebeu
o foco originalmente. Por isso, é útil sempre exibir um indicador de foco.
Se a resposta for "não", o controle poderá escolher mostrar um indicador de
foco de forma seletiva. Um bom exemplo é o elemento <button>
. Se um usuário clicar nele com
um mouse ou 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, é útil
mostrar um indicador de foco para que ele possa decidir se quer ou não
clicar no controle usando as teclas ENTER
ou SPACE
.
Evite outline: none
Francamente, a maneira como os navegadores decidem quando desenhar um indicador de foco é muito
confusa. Mudar a aparência de um elemento <button>
com CSS ou atribuir
um tabindex
a um elemento vai fazer com que o comportamento do anel de foco padrão 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 dele mostra como usar o 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 {
…
}