Barras de progresso de leitura, efeitos de parallax, elementos que aparecem ao entrar na tela: até pouco tempo atrás, tudo isso exigia um listener de scroll em JavaScript recalculando posições a cada frame. As Scroll-Driven Animations movem esse trabalho inteiro para o CSS, ligando o progresso de uma animação diretamente à posição de rolagem em vez do tempo, através da propriedade animation-timeline.
Como funciona
Toda animação CSS precisa de uma "linha do tempo" que dita seu progresso. Por padrão, essa linha do tempo é o relógio: a animação avança conforme os segundos passam. A propriedade animation-timeline troca esse relógio por uma linha do tempo baseada em scroll, usando uma de duas funções:
scroll(): o progresso segue a posição de rolagem de um container.view(): o progresso segue a visibilidade do próprio elemento dentro da área de rolagem.
Barra de progresso de leitura com scroll()
O exemplo mais direto é uma barra fixa no topo que se enche conforme a página rola:
.barra-progresso {
position: fixed;
top: 0;
left: 0;
height: 4px;
background: royalblue;
transform-origin: left;
animation: crescer linear;
animation-timeline: scroll(root);
}
@keyframes crescer {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
Aqui, scroll(root) liga a animação à rolagem do documento inteiro. Não existe duração real — o keyframe 0% corresponde ao topo da página e 100% ao fim, e o navegador interpola conforme o usuário rola.
Elementos que aparecem ao entrar na tela com view()
Para animar um elemento no momento em que ele entra na área visível — um efeito muito comum em landing pages — a função view() é mais adequada, pois sua linha do tempo é relativa à visibilidade do próprio elemento, não à rolagem da página inteira:
.card {
animation: aparecer linear both;
animation-timeline: view();
animation-range: entry 0% cover 40%;
}
@keyframes aparecer {
from {
opacity: 0;
transform: translateY(40px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
A propriedade animation-range recorta em que trecho da entrada do elemento a animação deve rodar — nesse caso, do instante em que ele começa a entrar na viewport até cobrir 40% dela, terminando a animação bem antes do elemento ficar totalmente visível.
Efeito parallax
Combinando scroll() com uma imagem de fundo maior que o container, dá para simular parallax sem nenhum JavaScript:
.hero {
overflow: hidden;
}
.hero img {
animation: subir linear;
animation-timeline: scroll(root);
animation-range: entry-crossing 0% exit-crossing 100%;
}
@keyframes subir {
from { transform: translateY(-10%); }
to { transform: translateY(10%); }
}
Nomeando containers de scroll
Quando a rolagem não acontece no documento inteiro, mas dentro de um container específico (um carrossel, por exemplo), é possível nomear esse container com scroll-timeline-name e referenciá-lo de qualquer elemento filho:
.carrossel {
overflow-x: auto;
scroll-timeline: --scroll-carrossel x;
}
.indicador {
animation: mover-indicador linear;
animation-timeline: --scroll-carrossel;
}
Quando usar
- Barra de progresso de leitura em posts de blog ou documentação longa.
- Elementos que fazem fade-in ou deslizam para a posição ao entrar na tela.
- Efeitos de parallax em imagens de destaque (hero sections).
- Indicadores de posição em carrosséis e galerias com scroll horizontal.
- Qualquer animação hoje implementada com
IntersectionObserverou listeners descrollque só precisa reagir à posição de rolagem.
Cuidados
Como não existe duração em tempo real, propriedades como animation-duration não fazem sentido aqui — quem controla o "tamanho" da animação é o próprio intervalo de rolagem, ajustado com animation-range. Vale também respeitar prefers-reduced-motion, desabilitando ou simplificando essas animações para quem prefere menos movimento na tela. Em navegadores sem suporte, a animação simplesmente não roda e o elemento fica no seu estado final de CSS — por isso é importante que o layout continue legível sem a animação, tratando-a como um reforço visual e não como algo essencial ao conteúdo.
Compatibilidade
O suporte já é bom nos navegadores baseados em Chromium e mais recente no Firefox e no Safari. Vale checar o suporte atual antes de depender dessa técnica como única forma de exibir conteúdo importante.
Conclusão
As Scroll-Driven Animations tiram do JavaScript um tipo de animação que sempre foi trabalhoso de sincronizar manualmente com a rolagem, entregando o cálculo de progresso para o próprio navegador. O resultado são animações mais suaves, que rodam fora da thread principal, com bem menos código do que a alternativa baseada em scroll e IntersectionObserver.
0 Comentário
Deixe seu Comentário!
Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.