6 motivos para o focus não funcionar (com e sem Javascript)
Tags: focus, html, elemento, tag
Published: 2022-10-19 23:57:38

## 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)](https://www.freecodecamp.org/news/4-reasons-your-z-index-isnt-working-and-how-to-fix-it-coder-coder-6bc05f103e6c/).
 
Expliquei sobre [o mínimo sobre focus com HTML, CSS e Javascript nesse post](https://demenezes.dev/posts/focus-em-elementos-html-css-javascript/). 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:
 
```html
<div>
  <!-- ... -->
</div>
```
 
```css
div {
  background-color: white;
}

div:focus {
  background-color: coral;
}
```
 
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:
 
```html
<div tabindex="0">
  <!-- Meu código -->
</div>
```
 
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:
 
```html
<button tabindex="-1">
  Botão não focalizável
</button>
```
 
Falei mais sobre o [tabindex nesse outro post](https://demenezes.dev/posts/focus-em-elementos-html-css-javascript/).
 
## A tag <input> possui um type="hidden"
 
Essa é fácil.
 
O focus não funciona pois ele é um recurso visual, e essa tag é oculta por padrão:
 
```html
<input type="hidden" />
```
 
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`.
 
```html
<input type="text" disabled />
<button type="submit" disabled>Enviar dados</button>
```
 
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`:
 
```html
<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>
```
 
Nesse post eu ensino um pouco mais sobre como trabalhar com [botões e links em HTML](https://demenezes.dev/posts/link-botao-button-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:
 
```javascript
button.focus();
openModal();
```
 
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:
 
```javascript
openModal();
button.focus();
```
 
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()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#noteshttps:/developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#notes)**, 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:
 
```html
<button id="click">CLICK</button>
<button id="focus">FOCUS</button>
```
 
Aqui tem dois botões, e o evento de `mousedown` no primeiro ativa o focus no segundo:
 
```javascript
document.getElementById('click').onmousedown = event => {
  document.getElementById('focus').focus();
}
```
 
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:
 
```javascript
document.getElementById('click').onmousedown = event => {
  event.preventDefault() // aqui a solução
  document.getElementById('focus').focus();
}
```
 
Vale lembrar que se o evento for de `onclick`, você não precisa adicionar essa linha:
 
```javascript
document.getElementById('click').onclick = event => {
  // nada
  document.getElementById('focus').focus();
}
```
 
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:
 
```html
<button class="visible">Botão visível</button>
<button class="invisible">Botão invisível</button>
```
 
```css
.visible {
  opacity: 1;
}

.invisible {
  opacity: 0;
}
```
 
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:
 
```css
.visible {
  opacity: 1;
}

.invisible {
  opacity: 0;
}

.invisible:focus {
  opacity: 1; /* Mostrando o botão invisível no focus */
}
```
 
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`.
 
![](https://www.datocms-assets.com/64896/1665946632-skip.png)
 
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:
 
```css
button {
  display: block;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: 0;
}
```
 
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:
 
```css
button:focus {
  display: block;
  min-width: 40px;
  min-height: 16px;
  padding: 1rem;
}
```
 
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:
 
```html
<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>
```
 
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)](https://www.datocms-assets.com/64896/1653006346-tim-mossholder-imld5dbclm4-unsplash-1.jpg)