Publicado em 26 de fevereiro de 2026
As animações movidas por rolagem evoluíram de implementações JavaScript irregulares da linha de execução principal para experiências suaves e acessíveis fora da linha de execução principal usando recursos modernos de CSS e interface, como linhas do tempo de rolagem e de visualização. Essa mudança permite a prototipagem rápida e animações de alto desempenho, além de permitir que as equipes criem páginas de contação de histórias (em inglês) refinadas, como demonstrado neste artigo.
NRK e narrativa
A NRK (Norwegian Broadcasting Corporation) é a emissora de serviço público da Noruega. A equipe por trás da implementação descrita neste artigo é chamada de Visuelle Historier em norueguês, que significa Histórias visuais em português. A equipe trabalha com design, gráficos e desenvolvimento para projetos editoriais de TV, rádio e Web, desenvolvendo identidades visuais, gráficos de conteúdo, artigos de destaque e novos formatos de narrativa visual. A equipe também trabalha com o perfil de design e as submarcas da NRK, criando ferramentas e modelos para facilitar a publicação de conteúdo de acordo com a identidade da marca.
Como a NRK usa animações de rolagem
As animações acionáveis e movidas por rolagem melhoram os artigos de narrativa, tornando-os mais interativos, envolventes e memoráveis. Essa abordagem é especialmente útil em narrativas de não ficção em que há poucas imagens ou nenhuma disponível.
Essas animações ajudam a fortalecer ou criar pontos dramáticos, impulsionar a história e desenvolver pequenas narrativas visuais que se alinham ou reforçam o texto. Por serem controladas pelo rolagem, essas animações permitem que o usuário controle a progressão da narrativa durante a rolagem.
Melhorar a experiência do usuário
Os insights de usuários do NRK revelam que os leitores apreciam como essas animações guiam o foco. Ao destacar textos ou animações enquanto rolam a tela, os usuários conseguem identificar os pontos principais e entender os aspectos mais importantes da história, especialmente ao ler rapidamente.
Além disso, a animação de gráficos pode simplificar informações complexas, facilitando a compreensão de relações e mudanças ao longo do tempo. Ao criar, adicionar ou destacar informações de forma dinâmica, a NRK pode apresentar conteúdo de uma maneira mais pedagógica e envolvente.
Definir um clima
As animações podem ser ferramentas poderosas para definir ou melhorar o clima de uma história. Ao ajustar o tempo, a velocidade e o estilo das animações, a NRK pode evocar emoções que correspondem ao tom da narrativa.
Dividir o texto e aliviar a visualização
A NRK costuma usar ilustrações animadas pequenas para dividir blocos longos de texto na forma de um dinkus simples ou uma pequena ilustração, aos leitores uma pausa momentânea na narrativa. Muitos usuários apreciam a variação, observando que ela divide o texto e o torna mais fácil de digerir. Eles acham que isso proporciona uma pausa bem-vinda na narrativa.
Respeitar as necessidades de acessibilidade e as preferências do usuário
As páginas públicas da NRK precisam estar acessíveis a todos os cidadãos da Noruega. Portanto, as páginas precisam respeitar a preferência do usuário por movimento reduzido. Todo o conteúdo da página precisa estar disponível para os usuários que ativaram essa configuração do navegador.
Como projetar animações de rolagem
A NRK simplificou o fluxo de trabalho de design desenvolvendo e integrando uma nova ferramenta de animação de rolagem diretamente ao sistema de gerenciamento de conteúdo Sanity. Desenvolvida em colaboração entre as equipes que desenvolvem e mantêm o site e as soluções de CMS, essa ferramenta permite que os designers criem protótipos e implementem animações de rolagem com dicas visuais para posições iniciais e finais de um elemento animado, além de poder visualizar animações em tempo real. Essa inovação oferece aos designers mais controle e acelera o processo de design diretamente no CMS.

Animações de rolagem no navegador
Animação com base em uma história
Este artigo sobre um homem que permaneceu morto no apartamento por nove anos teve que depender muito de ilustrações devido à falta de outros elementos visuais. As ilustrações foram animadas com rolagem para enfatizar a narrativa, como na animação em que a noite cai, as luzes em um edifício de vários andares acendem progressivamente até que apenas um apartamento permanece sem iluminação. A animação foi criada usando a ferramenta interna de animação de rolagem da NRK.
Animação de esmaecimento do texto
Este artigo começa com uma breve introdução, refletindo a sequência de abertura de um filme. Textos concisos combinados com visuais em tela cheia foram projetados para sugerir o conteúdo do artigo, criando expectativa para incentivar os leitores a ler o texto completo. A página de título foi criada para se parecer com um cartaz de cinema, com animações de rolagem usadas para reforçar essa sensação, animando o texto de cima para baixo.
.article-section {
animation: fade-up linear;
animation-timeline: view();
animation-range: entry 100% exit 100%;
}
Tipografia com animação de rolagem
Tipografia animada no título de um artigo: Férias médicas.
Com a introdução "Sjukt sjuke" (que significa "doente doente", em tradução livre), a NRK queria atrair os leitores para um artigo sobre o aumento das taxas de licença médica na Noruega. O título foi criado para chamar a atenção e dar aos leitores uma dica de que esta não é a história chata e cheia de números que eles esperam. A equipe da NRK queria que o texto e as ilustrações brincassem com os temas da peça, usando tipografia e animações de rolagem para melhorar isso. O artigo usa a nova fonte e o perfil de design do NRK News.
<h1 aria-label="sjuke">
<span>s</span><span>j</span><span>u</span><span>k</span><span>e</span>
<h1>
h1 span {
display: inline-block;
}
if (window.matchMedia('print, (prefers-reduced-motion: reduce)').matches) {
return;
}
const heading = document.querySelector("h1");
const letters = heading.querySelectorAll("span");
const timeline = new ViewTimeline({ subject: heading });
const scales = [/**/];
const rotations = [/**/];
for ([index, el] of letters.entries()) {
el.animate(
{
scale: ["1", scales[index]],
rotate: ["0deg", rotations[index]]
},
{
timeline,
fill: "both",
rangeStart: "contain 30%",
rangeEnd: "contain 70%",
easing: "ease-out"
}
);
}
Como destacar itens alinhados à rolagem
Os leitores que terminaram um artigo geralmente querem ler mais sobre o mesmo assunto. Nos artigos sobre jovens que abusam de substâncias em instituições, a NRK queria recomendar um único artigo como a próxima leitura, além de dar aos leitores a opção de ler outros artigos, se quisessem. A solução foi uma navegação deslizável implementada com ajuste de rolagem e animações movidas por rolagem. As animações garantiram que o elemento ativo estivesse em foco, enquanto os elementos restantes estavam desativados.
for (let item of items) {
const timeline = new ViewTimeline({ subject: item, axis: "inline" });
const animation = new Animation(effect, timeline);
item.animate(
{
opacity: [0.3, 1, 0.3]
},
{ timeline, easing: "ease-in-out", fill: "both" }
);
animation.rangeStart = "cover calc(50% - 100px)";
animation.rangeEnd = "cover calc(50% + 100px)";
}
Animação de rolagem acionar uma animação regular
Neste artigo sobre o orçamento nacional da Noruega, a NRK queria tornar uma história pesada e chata baseada em números mais acessível e personalizada. O objetivo era detalhar um número de orçamento enorme e incompreensível e dar ao leitor uma estimativa pessoal de como o dinheiro dos impostos está sendo gasto. Cada subseção se concentra em um item específico do orçamento nacional. A contribuição total de tributos do leitor foi simbolizada por uma barra azul dividida para revelar a contribuição do leitor para esses itens individuais. A transição foi alcançada com uma animação movida por rolagem que acionou os itens individuais para serem animados.
const timeline = new ViewTimeline({
subject: containerElement
});
// Setup scroll-driven animation
const scrollAnimation = containerElement.animate(
{
"--cover-color": ["blue", "lightblue"],
scale: ["1 0.2", "1 3"]
},
{
timeline,
easing: "cubic-bezier(1, 0, 0, 0)",
rangeStart: "cover 0%",
rangeEnd: "cover 50%"
}
);
// Wait for scroll-driven animation to complete
await scrollAnimation.finished;
scrollAnimation.cancel();
// Trigger time-driven animations
for (let [index, postElement] of postElements.entries()) {
const animation = postElement?.animate(
{ scale: ["1 3", "1 1"] },
{
duration: 200,
delay: index * 33,
easing: "ease-out",
fill: "backwards"
}
);
}
"Já fazemos animações de rolagem há muito tempo. Antes da API Web Animations, era necessário usar eventos de rolagem, combinados posteriormente com a API Intersection Observer. Essa era uma tarefa que consumia muito tempo, mas agora é simples com as APIs de animações da Web e de animações movidas por rolagem." —Helge Silset, desenvolvedor de front-end da NRK
O NRK tem muitos Componentes
da Web diferentes que podem ser conectados
a um dos elementos personalizados, chamado ScrollAnimationDriver
(<scroll-animation-driver>
), que oferece suporte às seguintes animações:
- Camadas com
[KeyframeEffects](https://developer.mozilla.org/docs/Web/API/KeyframeEffect)
- Animações Lottie
- mp4
- three.js
<canvas>
O exemplo a seguir usa camadas com KeyframeEffects
:
<scroll-animation-driver data-range-start='entry-crossing 50%' data-range-end='exit-crossing 50%'>
<layered-animation-effect>
<picture>
<source />
<img />
</picture>
<picture>
<source />
<img />
</picture>
<picture>
<source />
<img />
</picture>
</layered-animation-effect>
</scroll-animation-driver>
Implementação JavaScript de NRK do elemento personalizado <scroll-animation-driver>
:
export default class ScrollAnimationDriver extends HTMLElement {
#timeline
connectedCallback() {
this.#timeline = new ViewTimeline({subject: this})
for (const child of this.children) {
for (const effect of child.effects ?? []) {
this.#setupAnimationEffect(effect)
}
}
}
#setupAnimationEffect(effect) {
const animation = new Animation(effect, this.#timeline)
animation.rangeStart = this.rangeStart
animation.rangeEnd = this.rangeEnd
if (this.prefersReducedMotion) {
animation.currentTime = CSS.percent(this.defaultProgress * 100)
} else {
animation.play()
}
}
}
export default class LayeredAnimationEffect extends HTMLElement {
get effects() {
return this.layers.flatMap(layer => toKeyframeEffects(layer))
}
}
Desempenho de rolagem
A NRK tinha uma implementação de JavaScript muito eficiente antes de usar animações com base no rolagem, mas agora as animações com base no rolagem permitem que elas tenham um desempenho ainda melhor sem se preocupar com o problema de rolagem, mesmo em dispositivos de baixa potência.
- Duração da tarefa sem SDA: 1 ms.
- Duração da tarefa de SDA: 0,16 ms.

Para saber mais sobre a diferença na performance de rolagem entre implementações do JavaScript e animações orientadas a rolagem, o artigo Um estudo de caso sobre a performance de animações orientadas a rolagem explica mais detalhes.
Considerações sobre acessibilidade e UX
A acessibilidade tem um papel importante nas páginas públicas da NRK, já que elas precisam ser acessíveis a todos os cidadãos da Noruega em muitas circunstâncias. A NRK garante que as animações de rolagem sejam acessíveis de algumas maneiras diferentes:
- Respeitar as preferências do usuário para reduzir o movimento: use a consulta de mídia
screen and (prefers-reduced-motion: no-preference)
para aplicar a animação como um aprimoramento progressivo. Também é útil processar estilos de impressão ao mesmo tempo. - Considerando a ampla variedade de dispositivos e a precisão variável da entrada de rolagem: alguns usuários podem rolar em etapas (tecla de espaço ou teclas para cima/para baixo, navegando para pontos de referência usando um leitor de tela) e não ver toda a animação. Não perca informações cruciais.
- Ser cauteloso com animações que mostram ou ocultam conteúdo: para usuários que dependem do zoom do sistema operacional (SO), pode ser difícil notar que o conteúdo oculto vai aparecer conforme eles rolam a tela. Evite fazer com que os usuários precisem procurar. Se for necessário ocultar ou mostrar conteúdo, garanta a consistência de onde ele aparece e desaparece.
- Evitar grandes mudanças de brilho ou contraste na animação: como as animações movidas por rolagem dependem do controle do usuário, mudanças abruptas de luminância podem aparecer como piscadas, o que pode desencadear convulsões em alguns usuários.
@media (prefers-reduced-motion: no-preference) {
.article-image {
opacity: 0;
transition: opacity 1s ease-in-out;
}
.article-image.visible {
opacity: 1;
}
}
Suporte ao navegador
Para oferecer suporte a mais navegadores para ScrollTimeline e ViewTimeline, o NRK usa um polyfill de código aberto, que tem uma comunidade ativa que contribui para ele.
No momento, o polyfill é carregado condicionalmente quando ScrollTimeline
não está
disponível e usa uma versão simplificada do polyfill sem suporte a CSS.
if (!('ScrollTimeline' in window)) {
await import('scroll-timeline.js')
}
Suporte à detecção e ao processamento de navegadores no CSS:
@supports not (animation-timeline: view()) {
.article-section {
translate: 0 calc(-15vh * var(--fallback-progress));
opacity: var(--fallback-progress);
}
}
@supports (animation-timeline: view()) {
.article-section {
animation: --fade-up linear;
animation-timeline: view();
animation-range: entry 100% exit 100%;
}
}
No exemplo anterior para navegadores sem suporte, o NRK usa uma variável
CSS,
--fallback-progress
, como alternativa para controlar a linha do tempo da animação para
as propriedades translate
e opacity
.
A variável CSS --fallback-progress
é atualizada com um ouvinte de eventos
scroll
e
requestAnimationFrame
no JavaScript, assim:
function updateProgress() {
const end = el.offsetTop + el.offsetHeight;
const start = end - window.innerHeight;
const scrollTop = document.scrollingElement.scrollTop;
const progress = (scrollTop - start) / (end - start);
document.body.style.setProperty('--fallback-progress', clamp(progress, 0, 1));
}
if (!CSS.supports("animation-timeline: view()")) {
document.addEventListener('scroll', () => {
if (!visible || updating) {
return;
}
window.requestAnimationFrame(() => {
updateProgress();
updating = false;
});
updating = true;
});
}
Recursos
- Estudos de caso de animações com rolagem
- Demonstrações: animações movidas por rolagem
- Animar elementos na rolagem com animações de rolagem
- Codelab: Introdução às animações de rolagem no CSS
- Extensão do Chrome: depurador de animação acionado por rolagem
- Scroll-timeline Polyfill
- Informar um bug ou pedir um novo recurso? Queremos saber sua opinião.
Agradecemos especialmente a Hannah Van Opstal, Bramus e Andrew Kean Guan, do Google, e Ingrid Reime, da NRK, pelas contribuições valiosas a este trabalho.