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

2

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)

Reinvent your career. Join DEV.

It takes one minute and is worth it for your career.

Get started

DEV (this website) is a community where over one million developers have signed up to keep up with what's new in software.

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

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay