Skip to content

Tudo para WordPress, desenvolvimento web — e não só

🔄 Animação de objetos no scroll: guia passo a passo

🔄 Animação de objetos no scroll: guia passo a passo

Acede a um site, percorre a página e o logótipo no canto roda suavemente, reagindo a cada movimento da roda do rato. Parece dinâmico, tecnológico e acrescenta aquele toque especial que as pessoas notam.

Criar esta rotação é mais simples do que parece. Não precisa de bibliotecas pesadas nem de megabytes de frameworks de animação. Basta um div, algumas linhas de CSS e, literalmente, um bloco de JavaScript.

Abaixo encontra um guia passo a passo: desde a preparação da imagem até à adaptação para ecrãs móveis. O código está testado, a funcionar e não tem dependências.

💡 Visão geral rápida:

  • Prepare um objeto SVG ou PNG e insira-o no HTML
  • Fixe a posição com position: fixed e defina os deslocamentos com unidades de viewport
  • Adicione um handler de scroll em JavaScript que rode o objeto usando transform: rotate()
  • Ajuste a velocidade de rotação dividindo window.scrollY por um coeficiente
  • Para mobile, adicione uma media query com novo posicionamento e tempo de transição

1. Preparar o objeto

O objeto pode ser qualquer coisa: um ícone, logótipo, forma vetorial, símbolo de seta. Recomendo SVG, não perde nitidez durante as transformações e pesa quase nada. Se a transparência for crítica e não tiver um vetor, o PNG funciona.

Coloque a imagem dentro de um div contentor e insira-o no body, de preferência perto do topo. Um div separado simplifica a gestão: mais tarde pode adicionar elementos vizinhos ou substituir a imagem sem mexer na lógica de posicionamento.

1<div id="scrollContainer">
2 <img src="img/scrollObject.svg" alt="scrollObject" id="scrollObject">
3</div>

Pode ter vários objetos, basta atribuir um id único a cada um e duplicar a lógica JS vinculando-a ao seu próprio elemento. Mas, para já, vamos construir uma instância funcional.

2. Posicionamento com CSS

Onde colocar o objeto? Depende do objetivo:

  • Canto inferior direito, um ícone miniatura que não interfere com o conteúdo. Clássico para blogs e portfólios.
  • Canto superior esquerdo, indicador de posição de scroll (roda de progresso).
  • Centro do limite inferior, elemento decorativo grande que chama a atenção para o rodapé.

Vejamos o cenário do canto inferior direito, é universal e não cobre a navegação. Em CSS, escreva:

1#scrollObject {
2 position: fixed;
3 right: 3vw;
4 bottom: 3vh;
5 top: auto;
6 width: 7vh;
7 height: auto;
8 transition: 0.1s ease-out;
9}

A chave é position: fixed. Isto fixa o elemento em relação à janela do navegador, não ao documento. Ao fazer scroll, o conteúdo move-se, mas o objeto permanece no lugar. As unidades vw e vh (percentagens da largura e altura da viewport) ajustam automaticamente os deslocamentos para qualquer ecrã, do smartphone ao monitor 4K.

A propriedade transition: 0.1s ease-out suaviza os solavancos ao mudar de posição. Para a rotação, o seu papel é secundário, mas durante o redimensionamento ou mudanças de media query a transição parece mais limpa.

3. Animação de rotação com JavaScript

CSS consegue fazer @keyframes simples, mas a nossa tarefa é vincular o ângulo de rotação à posição de scroll. É aqui que entra o JavaScript. Código mínimo funcional:

1const scrollObject = document.getElementById("scrollObject");
2
3window.addEventListener("scroll", () => {
4 scrollObject.style.transform = `rotate(${window.scrollY}deg)`;
5});

O que está a acontecer aqui: window.scrollY devolve o número de pixéis que a página percorreu verticalmente. Este número é inserido na função CSS rotate(), um pixel de scroll equivale a um grau de rotação.

Se o objeto rodar demasiado rápido, divida o valor por um coeficiente:

1const speedFactor = window.scrollY / 2;
2const scrollObject = document.getElementById("scrollObject");
3
4window.addEventListener("scroll", () => {
5 scrollObject.style.transform = `rotate(${speedFactor}deg)`;
6});

Escolha um divisor que se adeque ao comprimento da sua página. Um valor de /2 reduz a rotação para metade, /4 torna-a suave e quase impercetível. Para landing pages longas, use /6 ou /8 para que o objeto não dê dez voltas completas a meio da página.

Nota de desempenho

O evento scroll dispara dezenas de vezes por segundo. Num site simples com um transform, isto é impercetível, mas se tiver vários objetos animados ou um DOM pesado, envolva a lógica em requestAnimationFrame:

1const scrollObject = document.getElementById("scrollObject");
2let ticking = false;
3
4window.addEventListener("scroll", () => {
5 if (!ticking) {
6 requestAnimationFrame(() => {
7 scrollObject.style.transform = `rotate(${window.scrollY}deg)`;
8 ticking = false;
9 });
10 ticking = true;
11 }
12});

O requestAnimationFrame agrupa as chamadas em frames de sincronização do navegador (normalmente 60 fps) e não executa o recálculo de estilos em cada evento de scroll, poupando CPU e bateria em dispositivos móveis.

Adicione também will-change: transform à regra CSS de #scrollObject. Isto diz ao navegador para alocar antecipadamente uma camada de composição da GPU, e a rotação será acelerada por hardware:

1#scrollObject {
2 /* ... other properties ... */
3 will-change: transform;
4}

4. Adaptação para mobile

Em ecrãs com menos de 600 pixéis, o canto inferior direito pode entrar em conflito com menus de hambúrguer ou botões "voltar ao topo". Uma solução sensata é mover o objeto para o centro inferior, para não cobrir elementos interativos:

1@media only screen and (max-width: 600px) {
2 #scrollObject {
3 transition: 0.2s ease-out;
4 margin-left: -4vh;
5 width: 8vh;
6 height: auto;
7 top: 10px;
8 left: 50%;
9 }
10}

O objeto move-se para o topo do ecrã, centrado usando left: 50% com margin-left negativo, uma técnica clássica de centragem horizontal. A largura é ligeiramente aumentada (8vh em vez de 7vh) para compensar a menor distância de visualização.

Note o transition: 0.2s ease-out na media query. Ao alternar de desktop para mobile (ou durante o redimensionamento da janela), o objeto não "salta" instantaneamente, mas desloca-se suavemente para a nova posição ao longo de 0,2 segundos.

Ícone de deslocamento no ecrã de um smartphone

Se estiver a trabalhar em Vue ou React, extraia o objeto de scroll para um componente separado. Pode anexá-lo ao App.vue raiz ou no layout para que a animação esteja presente em todas as páginas de uma vez, sem duplicação de código.

Resultado da animação do objeto de deslocamento após adaptação

Alternativa moderna: animações CSS orientadas por scroll

Em 2024-2025, os navegadores Chromium (Chrome, Edge, Opera) ganharam suporte nativo para animation-timeline: scroll(), animações vinculadas ao scroll sem uma única linha de JavaScript. Tem este aspeto:

1@keyframes rotate {
2 to { transform: rotate(360deg); }
3}
4
5#scrollObject {
6 animation: rotate linear;
7 animation-timeline: scroll();
8}

Pró: zero JavaScript, contra: apenas no Chromium para já (Firefox e Safari estão a implementar). Para melhoria progressiva, pode combinar: dê a versão CSS aos navegadores modernos e mantenha o handler JS como fallback para os restantes. Detalhes no MDN.

⁉️🤔 Perguntas frequentes

Posso animar não só a rotação, mas também a escala ou a opacidade?

Sim. O transform suporta várias funções ao mesmo tempo. Para fazer um objeto rodar e encolher com o scroll: scrollObject.style.transform = \rotate(${window.scrollY}deg) scale(${1 - window.scrollY / 5000})`;. A opacidade é tratada separadamente do transform, usando opacity. Combine até cinco ou seis parâmetros, mas teste, várias transformações em dispositivos fracos podem causar micro-engasgamentos. Um ou dois parâmetros mais will-change: transform` é um teto seguro para 60 fps.

**O que é melhor: SVG ou PNG para animação?**

SVG, sem dúvida. Escala sem perder nitidez em qualquer rotação e resolução de ecrã, pesa menos e o navegador renderiza-o como vetor (sem escadas de pixéis nos contornos após o rotate). Use PNG apenas se já tiver gráficos rasterizados prontos e não houver tempo para os refazer. Evite JPEG para objetos rotativos, os artefactos de compressão tornam-se mais visíveis após a rotação.

**Como faço para a animação começar apenas quando o objeto está na área visível?**

Use IntersectionObserver. Em vez de se vincular ao scroll global, monitoriza se o objeto entrou na viewport e só então ativa a rotação. Isto poupa recursos quando o elemento está fora do ecrã. Modelo básico: crie um observador com threshold: 0, no callback adicione/remova uma classe .active e vincule o handler de scroll JS à presença desta classe.

**Porque é que a animação engasga no meu site?**

Três causas típicas. Primeira: falta de will-change: transform, o navegador não entrega o elemento à composição da GPU e recalcula o layout a cada frame. Segunda: propriedades que causam reflow (como width, height, margin ou padding) são aplicadas ao elemento dentro do mesmo handler de scroll. Substitua-as por transform: scale() e transform: translate(). Terceira: o callback de scroll é executado sem requestAnimationFrame e gera repaints extra entre frames. Envolva a lógica no padrão rAF (exemplo na secção "Nota de desempenho").

**É necessário JavaScript? Existem soluções puramente CSS.**

As @keyframes de CSS estão vinculadas ao tempo, não à posição de scroll. Sim, o animation-timeline: scroll() muda o jogo, mas o suporte dos navegadores ainda é incompleto (ver secção 4). Em meados de 2026, a solução JavaScript com scrollY + transform continua a ser a forma mais fiável e compatível entre navegadores para vincular a rotação ao scroll. O código completo cabe em 5 linhas, não tem dependências e funciona do Internet Explorer 10 ao Chrome mais recente.

Deve adicionar animação de scroll ao seu site?

Rodar um objeto ao fazer scroll não é apenas um "truque fixe". É uma microinteração que dá ao visitante um feedback tátil: "estou a mover a página e algo está a acontecer". Bem configurada, não irrita nem distrai, mas acrescenta personalidade ao site.

Se o site for minimalista, limite-se a um pequeno objeto no canto e um coeficiente de /4 ou /6. Para landing pages e portfólios, pode arriscar mais: um elemento central grande com /2, animação combinada de rotação e escala, mudança de imagem ao atingir um determinado scrollY.

Regra principal: a animação de scroll deve complementar o conteúdo, não competir com ele pela atenção. Um objeto, movimento suave, sem intrusividade, e o seu site será memorável.