DEV Community

Cover image for 6 motivos para o focus não funcionar (com e sem Javascript)
deMenezes
deMenezes

Posted on • Edited on • Originally published at demenezes.dev

6 motivos para o focus não funcionar (com e sem Javascript)

Quando o focus não funciona, você pode verificar esses atributos HTML e alguns casos com Javascript.

O focus não funciona em:

  • Tags não focalizáveis por padrão (exemplo: div)
  • Tags com o atributo tabindex com valores negativos
  • Tags <input type="hidden" />
  • Tags input ou button com o atributo disabled
  • Tags <a> sem o atributo href
  • Elementos ocultos ou dentro de um elemento oculto
  • Dentro de um evento de mousedown sem um preventDefault()

Em alguns momentos o focus não funciona, não adianta.

Mas felizmente é fácil de descobrir o motivo.

Resolvi escrever esse artigo inspirado no post 4 razões pelas quais seu z-index não está funcionando (e como corrigi-lo).

Expliquei sobre o mínimo sobre focus com HTML, CSS e Javascript nesse post. Se você ainda conhece pouco sobre esse efeito, seria bem legal dar uma lida.

Para escrever esse artigo, testei o focus sempre de duas formas:

  1. Com a tecla tab até chegar no elemento
  2. E com o método element.focus(); do Javascript

Veja agora os motivos que fazem o focus não funcionar

O focus não funciona no elemento porque o tabindex não deixa

Se um elemento tiver o atributo tabindex com um valor negativo, dê adeus ao focus.

Esse é um recurso bem comum para desabilitar o foco no elemento. Porém funciona apenas para o focus via tecla tab, pois se você usar o element.focus(), ainda será possível focar.

É importante ficar claro que nem todos elementos são focalizáveis.

Uma div por exemplo, não pode receber focus em seu estado padrão:

<div>
  <!-- ... -->
</div>
Enter fullscreen mode Exit fullscreen mode
div {
  background-color: white;
}

div:focus {
  background-color: coral;
}
Enter fullscreen mode Exit fullscreen mode

O trecho background-color: coral só será visualizado, se você tornar essa div focalizável. Para isso, adicione o atributo tabindex com o valor 0 ou superior:

<div tabindex="0">
  <!-- Meu código -->
</div>
Enter fullscreen mode Exit fullscreen mode

Por outro lado, o tabindex também serve para desabilitar o focus em algum elemento focalizável por padrão. Você pode fazer isso em qualquer um deles, basta adicionar um valor negativo a esse atributo:

<button tabindex="-1">
  Botão não focalizável
</button>
Enter fullscreen mode Exit fullscreen mode

Falei mais sobre o tabindex nesse outro post.

A tag possui um type="hidden"

Essa é fácil.

O focus não funciona pois ele é um recurso visual, e essa tag é oculta por padrão:

<input type="hidden" />
Enter fullscreen mode Exit fullscreen mode

Essa tag é uma exceção, pois todos os outros campos de formulário são focalizáveis.

Além do atributo type="hidden" na input, existem outros atributos que podem fazer o focus não funcionar.

O atributo disabled está presente

O atributo disabled desativa um elemento.

Ele pode desabilitar todas as funcionalidades dos elementos de formulários, como inputs e buttons.

<input type="text" disabled />
<button type="submit" disabled>Enviar dados</button>
Enter fullscreen mode Exit fullscreen mode

Assim, além de desativar o clique e o preenchimento, eles também não podem receber focus.

O atributo href está ausente

A tag <a> é outra onde o focus não funciona por causa de atributos. Mas nesse caso, o navegador exige que você informe o destino do link através do atributo href:

<a href="my_page">É focalizável</a>
<a href="#">É focalizável</a>
<a href="">É focalizável</a>
<a href>É focalizável</a>
<a>Não é focalizável</a>
Enter fullscreen mode Exit fullscreen mode

Nesse post eu ensino um pouco mais sobre como trabalhar com botões e links em HTML.

O elemento focalizável está oculto ou dentro de um elemento oculto

Já perdi os cabelos uma vez no trabalho por causa desse motivo.

Imagine a situação: existe um botão que precisa receber focus assim que o modal (seu elemento pai) é aberto. Mas o focus não funcionava de jeito nenhum, e o código já estava cheio de console.log.

Assim que descobri o motivo, resolvi fazer esse post.

O código Javascript estava mais ou menos assim:

button.focus();
openModal();
Enter fullscreen mode Exit fullscreen mode

Ou seja, eu ativei o focus em um botão dentro de um modal oculto. Isso não funciona, a menos que eu inverta essas duas linhas:

openModal();
button.focus();
Enter fullscreen mode Exit fullscreen mode

Agora sim o focus funcionou, pois é aplicado em um elemento já visível na tela.

Esse problema acontece ao aplicar focus em um elemento:

  • Com display: none
  • Com visibility: hidden
  • Dentro de outro elemento com display: none
  • Dentro de outro elemento com visibility: hidden

Por fim, existe outra situação onde o focus não funciona, que é quando você usa Javascript.

O focus está dentro de um evento de mousedown sem um preventDefault()

Respira fundo que a explicação é longa.

Segundo o artigo da MDN sobre focus(), se você chamar esse método dentro de um evento de mousedown sem prevenir o comportamento default, o focus não funciona.

Veja agora parte por parte:

<button id="click">CLICK</button>
<button id="focus">FOCUS</button>
Enter fullscreen mode Exit fullscreen mode

Aqui tem dois botões, e o evento de mousedown no primeiro ativa o focus no segundo:

document.getElementById('click').onmousedown = event => {
  document.getElementById('focus').focus();
}
Enter fullscreen mode Exit fullscreen mode

Mas assim o foco permanecerá no button com id click, pois esse é o comportamento padrão do navegador: focar em um botão que foi clicado.

Para resolver isso, você deve prevenir o comportamento padrão, e logo depois disso ativar o focus no botão desejado:

document.getElementById('click').onmousedown = event => {
  event.preventDefault() // aqui a solução
  document.getElementById('focus').focus();
}
Enter fullscreen mode Exit fullscreen mode

Vale lembrar que se o evento for de onclick, você não precisa adicionar essa linha:

document.getElementById('click').onclick = event => {
  // nada
  document.getElementById('focus').focus();
}
Enter fullscreen mode Exit fullscreen mode

Mas o problema não é apenas quando o focus não funciona. Muitas vezes, funcionar também pode ser um problema

Motivos pelos quais o focus funciona (mas não deveria)

Me deixe-me eu me explicar-me.

Conforme eu testava tudo o que mostrei aqui, descobri que existem situações onde o focus funciona, mas não deveria. Os motivos:

  • Comportamento inesperado pelos usuários
  • Experiência ruim
  • Acessibilidade atrapalhada

A primeira situação é um elemento sem opacidade:

<button class="visible">Botão visível</button>
<button class="invisible">Botão invisível</button>
Enter fullscreen mode Exit fullscreen mode
.visible {
  opacity: 1;
}

.invisible {
  opacity: 0;
}
Enter fullscreen mode Exit fullscreen mode

O segundo botão, apesar de não ser visível na tela, é focalizável. Isso pode confundir o usuário.

Porém (atenção) se o botão com opacidade zero realmente precisa de focus, não deixe de trocar a opacidade dele para 1 usando a pseudoclasse:

.visible {
  opacity: 1;
}

.invisible {
  opacity: 0;
}

.invisible:focus {
  opacity: 1; /* Mostrando o botão invisível no focus */
}
Enter fullscreen mode Exit fullscreen mode

Um exemplo dessa aplicação são os botões de Skip to content. Para ver um deles em ação, pesquise qualquer coisa no Google, e tecle tab.

Se o seu elemento focalizável estiver dentro de outro elemento com opacidade zero, acontece a mesma coisa.

Outra situação onde o focus funciona, mas não deveria, é em elementos pequenos demais.

Se você criar um botão assim:

button {
  display: block;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: 0;
}
Enter fullscreen mode Exit fullscreen mode

Ainda será possível focar nele, apesar de ser quase impossível clicá-lo.

Aqui vale o mesmo aviso de antes: se o elemento pequeno demais realmente precisa de focus, não deixe de torná-lo maior quando isso acontecer. Algo como:

button:focus {
  display: block;
  min-width: 40px;
  min-height: 16px;
  padding: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

Por fim, existe uma diferença de comportamento quando o focus não funciona das duas maneiras testadas (com a tecla tab e com Javascript). Veja abaixo.

O que acontece quando o focus não funciona

Imagine um HTML simples com 3 links:

<a class="link-1" href="#"> <!-- o focus está aqui -->
  Link 1
</a>

<a class="link-2"> <!-- focus desabilitado -->
  Link 2
</a>

<a class="link-3" href="#">
  Link 3
</a>
Enter fullscreen mode Exit fullscreen mode

Suponha que o focus esteja no Link 1, e que esteja desabilitado no Link 2. Quando você pressionar tab, o focus saltará do Link 1 para o Link 3.

Por outro lado, caso tente focar o Link 2 via Javascript, o focus permanecerá no button 1.

Callback

Em alguns elementos, o focus não funciona. Entre eles:

  • Tag input do tipo hidden
  • Tag input com atributo disabled
  • Tag button com atributo disabled
  • Tag a sem atributo href
  • O elemento está oculto ou dentro de um elemento oculto
  • O focus é aplicado dentro de um evento de mousedown sem um preventDefault()

Por outro lado, o focus pode funcionar e confundir o usuário. Então revise os elementos que recebem focus porém estão invisíveis pela propriedade opacity ou pequenos demais para serem clicados e visualizados.

Quando o focus não funciona em algum elemento, a tecla tab "pula" e foca no próximo. Já em Javascript, o elemento focado continua sendo o último.

Você sempre pode descobrir qual é o elemento em foco através da propriedade document.activeElement.

Obrigado pela sua leitura.

E focus nos estudos!

Escrita "laugh" em letra neon (risada em inglês)

Top comments (2)

Collapse
 
oneyottabyte profile image
Dorian Junior

No meu caso, o problema foi z-index mau configurado.

Collapse
 
demenezes profile image
deMenezes

Acontece hehehe

Não por acaso, já tentaram solucionar esse problema com uma lib: Z-Index Manager

github.com/vispo/ZIndexMgr