Introdução: Quando o CSS Age como JavaScript

Você já quis estilizar um elemento quando um filho está focado, ou detectar a abertura de um popover sem escrever uma linha de JavaScript? O CSS moderno evoluiu para lidar com muitas interações baseadas em estado que antes exigiam event listeners do JavaScript. Não se trata de substituir o JavaScript, mas de entender a sobreposição e usar a ferramenta certa para cada tarefa.

Neste guia, vamos explorar as pseudo-classes que se comportam como event listeners, compará-las com suas equivalentes em JavaScript e olhar para o futuro da propriedade event-trigger, que pode mudar a forma como pensamos sobre animações CSS.

As Pseudo-Classes que Escutam Eventos

:hover e :active

A pseudo-classe :hover corresponde ao momento em que o ponteiro está sobre um elemento, o que equivale aos eventos pointerenter e pointerleave. Já :active se aplica enquanto um elemento está sendo pressionado, semelhante a pointerdown e pointerup.

button:hover {
  background-color: #0056b3;
}

button:active {
  transform: scale(0.98);
}

:focus e :focus-visible

:focus é similar aos eventos focus/blur, mas :focus-visible adiciona heurísticas do navegador para decidir se um indicador de foco deve ser mostrado, tipicamente para navegação por teclado. Isso é crucial para acessibilidade, e você pode até verificar isso via JavaScript:

element.addEventListener("focus", (event) => {
  if (event.target.matches(":focus-visible")) {
    // Mostrar anel de foco
  }
});

:focus-within e :has()

:focus-within corresponde a um elemento se algum de seus descendentes tiver foco. A mais poderosa :has() pode corresponder a qualquer relação de seletores. Ambas podem substituir lógica complexa de travessia do DOM em JavaScript.

form:focus-within {
  border-color: #4CAF50;
}

form:has(:focus) {
  border-color: #4CAF50;
}

:checked, :valid e Mais

Estados de elementos de formulário como :checked, :valid, :invalid, e até :user-valid/:user-invalid são gerenciáveis em CSS sem JavaScript. Por exemplo, :user-valid só se aplica após o usuário interagir com o campo e sair dele, o que é similar ao evento change.

input:user-valid {
  border-color: green;
}

input:user-invalid {
  border-color: red;
}

Pseudo-Classes de Elementos de Mídia

Pseudo-classes mais novas como :paused, :playing e :buffering permitem estilizar elementos <video> e <audio> baseado no estado de reprodução, que antes exigia event listeners em JavaScript.

video:playing {
  opacity: 1;
}

video:paused {
  opacity: 0.5;
}

:popover-open, :modal e :fullscreen

Essas pseudo-classes correspondem diretamente a estados de popovers, diálogos e elementos em tela cheia, eliminando a necessidade de handlers de toggle ou fullscreenchange.

.popover:popover-open {
  display: block;
}

dialog:modal {
  background: white;
}

O Futuro: Propriedade event-trigger

Além das pseudo-classes, a especificação de Animation Triggers do CSS propõe uma propriedade event-trigger que permitiria disparar animações baseadas em eventos reais. Embora ainda não suportada nos navegadores, a ideia é definir eventos customizados e vinculá-los a animações.

@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

button {
  event-trigger: --event click;
}

div {
  animation-trigger: --event play-forwards;
  animation: fade-in 300ms both;
}

Isso pode abrir novas possibilidades para controle declarativo de animações, reduzindo a necessidade de JavaScript em muitos cenários interativos.

Limitações e Cuidados

Embora esses recursos CSS sejam poderosos, não são uma bala de prata. Interações complexas, mudanças dinâmicas de estado ou lógica que não seja CSS ainda exigem JavaScript. Além disso, o suporte dos navegadores varia, então sempre verifique a compatibilidade antes de usar esses recursos em produção.

Conclusão: Escolha a Ferramenta Certa

Entender a sobreposição entre pseudo-classes CSS e eventos JavaScript permite escrever código mais limpo e sustentável. Use CSS para estilização baseada em estado simples e reserve JavaScript para lógica complexa. Para um mergulho mais profundo em técnicas de layout CSS, confira nosso guia sobre CSS translate().

Developer comparing CSS pseudo-class selectors with JavaScript event listeners in browser devtools Dev Environment Setup

Principais Pseudo-Classes e Equivalentes em JavaScript

Abaixo está uma tabela de referência rápida para pseudo-classes comuns e os eventos que elas imitam:

Pseudo-ClasseEquivalente em JavaScript
:hoverpointerenter / pointerleave
:activepointerdown / pointerup
:focusfocus / blur
:focus-withinfocusin / focusout
:checkedchange
:valid / :invalidinvalid / checkValidity()
:paused / :playingpause / play
:popover-opentoggle
:fullscreenfullscreenchange

Exemplo Prático: Validação de Formulário Sem JavaScript

Vamos ver como você pode construir um formulário que mostra estados de validação apenas com CSS, usando :user-valid e :user-invalid. Essa abordagem dá feedback imediato após o usuário interagir com o campo, melhorando a experiência sem scripts extras.

<form>
  <label for="email">Email:</label>
  <input type="email" id="email" required>
</form>
input:user-valid {
  border: 2px solid green;
}

input:user-invalid {
  border: 2px solid red;
}

input:user-invalid:focus::after {
  content: "Por favor, insira um email válido";
  color: red;
  font-size: 0.9em;
}

Esse padrão não só é mais limpo, mas também mais performático, pois evita listeners de JavaScript para cada input.

Web page showing form validation states with CSS pseudo-classes and JavaScript code Technical Structure Concept

Limitações e Considerações

Embora esses recursos CSS reduzam o trabalho braçal, eles têm limitações:

  • Suporte dos Navegadores: Muitas pseudo-classes são novas e podem não ser suportadas em navegadores antigos. Sempre teste.
  • Lógica Complexa: Se você precisa reagir a múltiplas condições ou executar efeitos colaterais, JavaScript ainda é necessário.
  • Acessibilidade: Depender apenas de CSS para mudanças de estado pode não transmitir mudanças para tecnologias assistivas. Use atributos ARIA quando necessário.

Próximos Passos para Aprender

Para dominar essas técnicas, tente converter seus event listeners de JavaScript em pseudo-classes CSS quando possível. Além disso, fique de olho na proposta de event-trigger e experimente em seus demos. Para mais insights sobre CSS, explore nosso artigo sobre o novo capítulo da React Foundation.

CSS animation trigger example using event-trigger property in a code editor Algorithm Concept Visual

Conclusão

As pseudo-classes CSS oferecem uma forma declarativa de lidar com mudanças de estado na interface, muitas vezes simplificando o código e melhorando a performance. Ao entender suas contrapartes em JavaScript, você pode tomar decisões informadas sobre quando usar cada abordagem. Comece pequeno, teste bastante e aproveite o código mais limpo!

Leitura Recomendada:

Este conteúdo foi elaborado com o auxílio de ferramentas de IA, com base em fontes confiáveis, e revisado pela nossa equipe editorial antes da publicação. Não substitui o aconselhamento de um profissional especializado.