W3docs

Eventos focus e blur em JavaScript

Aprenda como os eventos focus e blur do JavaScript funcionam, como diferem de focusin e focusout, e como usá-los para validação de formulários e acessibilidade.

O JavaScript oferece controle preciso sobre qual elemento está atualmente focado — o elemento que recebe a entrada do teclado. Os eventos focus e blur permitem reagir no momento em que um elemento ganha ou perde o foco, o que é a base para validação inline de formulários, destaque do campo ativo, criação de widgets acessíveis pelo teclado e orientação dos usuários por um formulário. Este artigo aborda o que são esses eventos, como diferem de seus equivalentes com borbulhamento focusin/focusout, e vários padrões práticos.

Esta página baseia-se na introdução a eventos do navegador. Se você precisar lidar com eventos em muitos elementos ao mesmo tempo, leia também sobre borbulhamento e captura.

Entendendo Focus e Blur em JavaScript

O evento focus é disparado quando um elemento se torna o alvo ativo da entrada do teclado — o elemento para o qual document.activeElement aponta. O evento blur é disparado quando esse elemento perde o foco, por exemplo porque o usuário clicou em outro lugar, pressionou Tab ou o foco foi movido programaticamente.

Por padrão, apenas elementos interativos podem receber foco: links (<a href>), controles de formulário (<input>, <textarea>, <select>, <button>) e alguns outros. Para tornar qualquer elemento focável — um <div>, <span> ou <li> — dê a ele um atributo tabindex. Use tabindex="0" para colocá-lo na ordem natural de tabulação, ou tabindex="-1" para torná-lo focável apenas via script (element.focus()).

Um ponto crítico a observar: focus e blur não borbulham. Um listener anexado a um elemento pai não será disparado quando um input descendente ganhar foco. Quando você precisar de delegação de eventos em um contêiner, use os equivalentes com borbulhamento focusin e focusout — eles se comportam de forma idêntica, mas propagam pela árvore DOM.

Focus vs. Blur vs. Focusin vs. Focusout

EventoDisparado quandoBorbulha?
focuselemento ganha focoNão
blurelemento perde focoNão
focusinelemento ganha focoSim
focusoutelemento perde focoSim

Para um único elemento conhecido, focus/blur são os mais simples. Para um formulário inteiro ou uma lista de campos, anexe focusin/focusout uma vez no contêiner.

Como Implementar Eventos Focus

Para usar o evento focus, anexe um listener ao elemento. O exemplo abaixo destaca um input no momento em que ele ganha foco:

<input type="text" id="nameInput" placeholder="Enter Your Name">
<script>
  document.getElementById('nameInput').addEventListener('focus', function(event) {
    event.target.style.backgroundColor = 'lightblue';
  });
</script>

Este trecho de código torna o fundo do campo de input azul claro quando ele recebe foco, melhorando a interface do usuário ao indicar onde o usuário está digitando no momento. Para estilização simples, considere usar a pseudo-classe CSS `:focus` como uma alternativa padrão sem JavaScript:

input:focus {
  background-color: lightblue;
}

Como Implementar Eventos Blur

Validar no blur é um dos usos mais comuns desses eventos: você deixa o usuário terminar de digitar e verifica o valor quando ele sai do campo. Veja como validar um endereço de e-mail quando o input perde o foco:

<input type="email" id="emailInput" placeholder="Enter Your Email">
<script>
  document.getElementById('emailInput').addEventListener('blur', function(event) {
    // Simplified regex for educational purposes
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(event.target.value)) {
      alert('Please enter a valid email address.');
      event.target.style.backgroundColor = 'salmon';
    } else {
      event.target.style.backgroundColor = 'lightgreen';
    }
  });
</script>

Este script verifica se o e-mail digitado corresponde a um formato de e-mail padrão e alerta o usuário se a entrada for inválida. A cor de fundo muda para verde se válida e para salmão se não, fornecendo feedback visual imediato.

Focando Elementos com Script

Além de reagir a eventos, você pode mover o foco você mesmo com element.focus() e removê-lo com element.blur(). Isso é útil para enviar o cursor ao primeiro campo no carregamento da página, ou retornar o foco a um campo inválido após a validação.

<input id="search" placeholder="Search..." />
<button id="go">Focus the search box</button>
<script>
  document.getElementById('go').addEventListener('click', () => {
    document.getElementById('search').focus();
  });
</script>

Dois extras úteis:

  • document.activeElement sempre retorna o elemento que atualmente tem foco (ou <body> se nenhum tiver). É útil para verificar o estado do foco sem listeners.
  • focus({ preventScroll: true }) foca um elemento sem rolar para exibi-lo — útil quando você gerencia a rolagem você mesmo.

Para um campo que deve ser focado assim que a página carregar, o atributo HTML autofocus (<input autofocus>) é a opção declarativa sem JavaScript.

Usando focusin/focusout para Delegação

Como focus e blur não borbulham, anexar um listener a um formulário não capturará mudanças de foco nos seus inputs. Os eventos com borbulhamento focusin/focusout resolvem isso — você gerencia cada campo a partir de um único listener no elemento pai:

<form id="signup">
  <input name="email" placeholder="Email" />
  <input name="password" type="password" placeholder="Password" />
</form>
<script>
  const form = document.getElementById('signup');
  form.addEventListener('focusin', (event) => {
    event.target.style.outline = '2px solid royalblue';
  });
  form.addEventListener('focusout', (event) => {
    event.target.style.outline = '';
  });
</script>

O evento focusout também expõe event.relatedTarget — o elemento que receberá o foco a seguir — o que permite saber para onde o foco está indo.

Técnicas Avançadas: Gerenciando Múltiplos Campos

Quando um usuário preenche corretamente um campo do formulário, você pode mover automaticamente o foco para o próximo input ao sair do campo atual. Isso simplifica o preenchimento do formulário, eliminando a necessidade de cliques manuais. Veja como implementar esse comportamento:

<input type="text" id="firstName" placeholder="First Name" />
<input type="text" id="lastName" placeholder="Last Name" />
<div id="error" style="color: red;"></div> <!-- Display error message here -->
<script>
  document.getElementById('firstName').addEventListener('blur', validateFirstName);

  function validateFirstName(event) {
    const input = event.target;
    const errorDiv = document.getElementById('error');
    // Allow only letters and spaces, must not be empty
    const nameRegex = /^[A-Za-z ]+$/;
    if (!nameRegex.test(input.value)) {
      errorDiv.textContent = 'Please enter a valid first name.'; // Display error message
      input.style.backgroundColor = 'salmon'; // Set background to salmon on invalid input
      input.focus(); // Keep focus on the first name input to encourage correction
    } else {
      input.style.backgroundColor = 'white'; // Reset background to white on valid input
      errorDiv.textContent = ''; // Clear error message
      document.getElementById('lastName').focus(); // Optionally move focus to the last name input
    }
  }
</script>

Este exemplo move automaticamente o foco para o campo lastName assim que um primeiro nome válido é inserido, melhorando a experiência do usuário ao reduzir a necessidade de cliques manuais.

Chamar input.focus() dentro de um handler blur pode conflitar com o usuário. Se eles estavam tentando clicar em um elemento diferente, refocalizar o campo pode parecer uma armadilha. Use esse padrão com moderação e prefira exibir uma mensagem de erro que o usuário possa corrigir no seu próprio ritmo.

Armadilhas Comuns

  • Não espere que focus/blur borbulhem. Um listener em um contêiner para focus nunca será disparado; mude para focusin/focusout para delegação.
  • blur é executado antes que o clique em outro controle seja concluído. Se um handler blur ocultar ou remover um elemento que o usuário acabou de clicar, o clique pode não ser registrado — verifique event.relatedTarget primeiro.
  • Elementos ocultos ou com display:none não podem receber foco. element.focus() silenciosamente não faz nada neles.
  • Forçar o foco prejudica a acessibilidade quando é inesperado. Mantenha a ordem de tabulação do teclado previsível e evite prender o foco.
  • Para estilização visual pura do foco, prefira as pseudo-classes CSS :focus / :focus-visible em vez de JavaScript — elas não requerem listeners e funcionam corretamente com interação apenas pelo teclado.

Conclusão

Os eventos de foco e blur são a espinha dorsal de formulários interativos e acessíveis. Saber que focus/blur não borbulham (e que focusin/focusout borbulham), como mover o foco com element.focus(), e onde traçar a linha entre JavaScript e a pseudo-classe CSS :focus permite criar experiências de entrada responsivas sem surpreender seus usuários.

A seguir, explore interações relacionadas do navegador: eventos de teclado, os eventos change, input, cut, copy, paste e borbulhamento e captura para delegação.

Prática

Prática
Quais das afirmações a seguir estão corretas sobre os eventos focus e blur em JavaScript?
Quais das afirmações a seguir estão corretas sobre os eventos focus e blur em JavaScript?
Was this page helpful?