Olha só isso: o CSS vai aposentar seu IntersectionObserver 🚀

Se você já passou horas escrevendo callbacks de IntersectionObserver só pra fazer um elemento aparecer com fade quando entra na viewport, respira fundo. Vem aí uma solução nativa.

A nova propriedade animation-trigger faz exatamente isso: ela atrasa o início de uma animação CSS até que um trigger nomeado seja acionado — seja por posição de scroll, interseção de viewport ou até evento do DOM (tipo um clique).

.element {
  /* Espera o --trigger ativar, toca pra frente ao entrar e pra trás ao sair */
  animation: fade-in 0.35s ease-in-out both;
  animation-trigger: --trigger play-forwards play-backwards;
}

Uma linha substitui um bloco considerável de JS. Bora entender como isso funciona de verdade.

⚠️ Atenção, dev: a spec ainda está em Editor's Draft e só roda no Chrome 145+. Trate como experimental até ter suporte mais amplo.

O artigo original sobre animation-trigger é a 근거자료 se você quiser se aprofundar na spec.

Developer writing CSS animation-trigger property code in a modern editor for scroll-triggered effects Coding Session Visual

Como o animation-trigger funciona de verdade

Sintaxe

animation-trigger: none | <nome-do-trigger> <ação> [<ação>];
  • none — padrão; a animação se comporta normalmente.
  • <nome-do-trigger> — um dashed ident (ex.: --fade-in-trigger) que precisa bater com um nome definido por timeline-trigger ou event-trigger.
  • <ação> — o que fazer quando o trigger ativa (e opcionalmente, quando desativa).

As ações disponíveis

AçãoComportamento
play-forwardsToca pra frente (playback rate positivo)
play-backwardsToca ao contrário
playToca na taxa atual
play-onceToca só do estado inicial/pausado; ignora se já terminou
pauseCongela no lugar
resetVolta o progresso pra 0 e pausa
replayVolta pra 0 e toca na hora
noneNão faz nada

Algumas ações não são exclusivas — dá pra combinar play-backwards na entrada com play-forwards na saída pra efeitos reversíveis.

Configurando um timeline-trigger

Você não usa animation-trigger sozinho. Primeiro precisa de uma fonte de trigger:

.trigger {
  /* Shorthand: nome | fonte | activation-range / active-range */
  timeline-trigger: --trigger scroll() contain / cover;
}

Separando em longhands:

.timeline-trigger-name: --fade-in;
timeline-trigger-source: view();
timeline-trigger-activation-range: contain;
timeline-trigger-active-range: cover;
  • activation-range — quando o trigger liga (ex.: contain = elemento totalmente visível).
  • active-range — o limite externo onde o trigger continua ativo. Se omitir, herda o activation range.
  • O active range precisa incluir o activation range, senão o trigger nunca liga.

Diferente de background ou border, a ordem do shorthand é fixa. Não embaralha.

Ligando na animação

/* Trigger fica num elemento sentinela pai */
.trigger {
  timeline-trigger: --trigger scroll() contain / cover;
}

/* Animação aplica em quantos filhos quiser */
.text {
  animation-trigger: --trigger play;
  animation: fade 0.6s ease-out;
}

Como trigger e animação são desacoplados, um trigger pode dirigir vários elementos. Coloca um sentinela no topo da seção e todos os filhos animam juntos quando entram na viewport — sem observer por elemento.

Escopo de triggers

Por padrão, nomes de trigger são globais. Se dois elementos declaram --trigger, o último na cascata vence. Use trigger-scope pra restringir a um subtree do DOM — essencial pra componentes reutilizáveis.

Laptop screen showing Chrome DevTools inspecting CSS timeline-trigger and animation-trigger values Software Concept Art

Scroll-triggered vs. scroll-driven: NÃO é a mesma coisa

Essa é a confusão mais comum. Os nomes parecem iguais, os dois usam scroll, mas resolvem problemas diferentes.

AspectoScroll-DrivenScroll-Triggered
Modelo de progressoContínuo, atrelado ao offset do scrollEstado binário (on/off)
TimingScrubbing frame a frame com o scrollDispara uma vez, depois roda como animação CSS normal
Reversível?Sim, naturalmenteSó se você definir ação de desativação
Uso típicoParallax, barras de progresso, reveals stickyFade-ins, reveals pontuais, chamar atenção
Propriedade chaveanimation-timeline: scroll()animation-trigger: --x play

Resumindo: scroll-driven = scrub, scroll-triggered = dispara. Se precisa rebobinar conforme sobe, é scroll-driven. Se precisa de um momento discreto de "entrou, toca", é trigger.

Cuidados que você NÃO pode ignorar

  • Só Chrome 145+. Firefox e Safari ainda não entregaram. Qualquer uso em produção hoje precisa de feature query ou fallback pra IntersectionObserver.
  • Status de Editor's Draft. A spec pode mudar. Nomes, keywords e ordem do shorthand não estão congelados.
  • Escopo global por padrão. Fácil de colidir em codebases grandes; sempre use trigger-scope em componentes.
  • Sem animation-trigger sem fonte. Você ainda precisa de timeline-trigger ou event-trigger configurado.
  • Debug é chato. O suporte do DevTools pra ranges de ativação ainda está amadurecendo.

Se você curte pipelines com "human-in-the-loop" em projetos open source, os mesmos princípios de escopo e fallback se aplicam — dá uma olhada no pipeline semanal do huggingface_hub pra ver um paralelo em CI.

Web designer previewing scroll-triggered text reveal animation in browser with CSS animation-trigger property IT Technology Image

Onde isso nos deixa

animation-trigger é a direção certa pra plataforma web: menos observers em JS, mais CSS declarativo e uma separação limpa entre o que anima e quando dispara. Só o desacoplamento trigger/animação já vale o preço — um sentinela, vários filhos animando.

Mas não tá pronto pra produção. Só Chrome, Editor's Draft, sem degradação graciosa embutida. O jogo pragmático hoje é:

  1. Prototipe com ele. Familiarize-se com a sintaxe agora pra estar pronto quando Safari e Firefox entregarem.
  2. Use feature query. Envolva o uso em @supports (animation-trigger: none) e mantenha o fallback com IntersectionObserver vivo.
  3. Escopar triggers. Não deixe nomes globais se tornarem o próximo !important.

O que estudar depois

  • Scroll-driven animations (animation-timeline: scroll()) — a spec irmã que você vai querer no mesmo kit.
  • trigger-scope — pra isolar triggers dentro de Web Components.
  • Event triggers — a spec também suporta eventos do DOM, não só timeline.

Leitura relacionada

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.