- Artigos
- Desenvolvimento
- Apresentando o ReVue: animações de reveal compatíveis com SSR no Nuxt

Todo portfólio, landing page e site institucional acaba pedindo a mesma coisa: elementos que aparecem com fade ou deslizamento conforme o usuário rola a página. Em uma aplicação Vue comum, basta instalar uma biblioteca de scroll-reveal e seguir em frente. No Nuxt, a história é outra. A renderização no servidor entrega o HTML completo antes do JavaScript executar. Se a biblioteca esconde o conteúdo no servidor e só revela no cliente, o usuário vê um flash — o conteúdo some e reaparece com animação. É um problema de hidratação esperando para acontecer.
Foi por isso que criei o ReVue: do jeito que eu realmente quero trabalhar, com uma única diretiva, defaults sensatos e sem componentes wrapper poluindo os templates. O pacote está publicado no npm como nuxt-revue, e você pode ver tudo funcionando no site de demonstração.
Por que mais um módulo de animação?
Antes de escrever o ReVue, testei os caminhos habituais. Registrar uma diretiva de terceiros como plugin client-only funciona, mas você perde tipagem, precisa de stubs no servidor e acaba copiando configurações ligeiramente diferentes em cada projeto. Bibliotecas baseadas em componentes resolvem o SSR envolvendo o conteúdo, mas isso altera a estrutura do DOM e complica listas escalonadas — você acaba passando índices por slots ou aninhando componentes que não pediu.
O que eu queria era mais próximo de como os módulos Nuxt costumam funcionar:
- Uma diretiva — aplique
v-revealem qualquer elemento, sem componentes wrapper. - Defaults globais — configure timing e comportamento de disparo uma vez no
nuxt.config.ts, com override local quando necessário. - Seguro para SSR — o conteúdo fica visível no servidor; a animação roda só depois da hidratação.
- Leve — o pacote tem cerca de 15 KB descompactado, com uma única dependência de runtime no
@nuxt/kit.
O ReVue não tenta ser um framework de animação genérico. Ele faz uma coisa — revelar elementos no mount ou ao entrar no viewport — e faz isso de um jeito que combina com o modelo de renderização do Nuxt.
Instalação
O ReVue segue o fluxo padrão de instalação de módulos Nuxt. O caminho mais rápido é o comando module add:
npx nuxt module add nuxt-revueOu instale e registre manualmente:
npm install nuxt-revueexport default defineNuxtConfig({
modules: ['nuxt-revue'],
})Isso é tudo para a experiência padrão. O módulo registra a diretiva v-reveal e inclui uma folha de estilo pequena — sem imports extras, sem arquivos de plugin para manter.
Uso básico
O caso mais simples revela um elemento quando a página carrega:
<h1 v-reveal>
Revelado no carregamento da página
</h1>Passe um objeto de opções para personalizar o timing. Os valores de delay e duration são em milissegundos; distance é o deslocamento vertical em pixels:
<section
v-reveal="{
delay: 150,
duration: 600,
distance: 32,
}"
>
Reveal personalizado
</section>Por baixo dos panos, o ReVue adiciona custom properties CSS — --reveal-delay, --reveal-duration e --reveal-distance — e alterna as classes reveal e reveal--in. A animação é um fade-in com translateY e uma curva de easing suave. Nada exótico, e é exatamente isso o ponto: movimento previsível que funciona bem em landing pages.
Defaults globais da aplicação
Na maioria dos meus projetos, quero reveals disparados pelo scroll com timing consistente. Em vez de repetir opções em cada elemento, o ReVue suporta defaults no nível do módulo pela chave reVue.reveal:
export default defineNuxtConfig({
modules: ['nuxt-revue'],
reVue: {
reveal: {
when: 'visible',
duration: 700,
distance: 32,
threshold: 0.2,
once: true,
},
},
})Com essa configuração, um v-reveal sem opções herda todos esses valores. Overrides locais fazem merge por cima — então um card de preço pode definir só { delay: 80 } enquanto o resto vem da config. Esse padrão mantém os templates limpos e facilita ajustar tokens de design em um único lugar.
O site de demo em nuxt-revue.lucassimines.dev mostra exatamente esse fluxo: defaults da app, diretivas sem opções e overrides locais lado a lado.
Reveals disparados pelo scroll
Definir when: 'visible' troca a animação no mount pela detecção de viewport via IntersectionObserver. É o modo que mais uso para conteúdo abaixo da dobra:
<section
v-reveal="{
when: 'visible',
threshold: 0.2,
rootMargin: '0px 0px -10% 0px',
}"
>
Revelado ao entrar no viewport
</section>A opção threshold controla quanto do elemento precisa estar visível antes da animação disparar. O rootMargin permite antecipar ou atrasar o trigger em relação à borda do viewport — útil em hero sections onde você quer que o conteúdo anime assim que entra no enquadramento.
Por padrão, once: true faz com que reveals disparados por visibilidade rodem apenas na primeira vez que o elemento entra no viewport. Rolar de volta para cima não repete a animação. Para comportamento de replay, use once: false.
Listas escalonadas
Reveals escalonados são um dos padrões mais comuns em grids de features e layouts de cards. Com o ReVue, você calcula o delay a partir do índice do loop — sem componente especial de lista:
<article
v-for="(item, index) in items"
:key="item.id"
v-reveal="{
delay: index * 100,
}"
>
{{ item.title }}
</article>Combinado com defaults globais em when: 'visible', cada card revela em sequência conforme a seção entra no viewport. A seção de cards do site de demo mostra esse padrão com override de delay apenas por card.
Evitando replays indesejados
Quando o Vue remonta uma seção — após troca de rota, toggle condicional ou atualização de lista com key — as animações podem disparar de novo mesmo que o usuário já as tenha visto. O ReVue resolve isso com onceKey:
<section v-reveal="{ onceKey: 'pricing' }">
Preços
</section>Elementos que compartilham o mesmo onceKey são rastreados como grupo. Depois de revelados, esse grupo não anima de novo durante a sessão da página. É um detalhe pequeno, mas evita aquela reanimação incômoda que aparece quando abas ou accordions remontam conteúdo.
Como a segurança de SSR funciona
O problema de hidratação na maioria das bibliotecas de reveal vem de definir opacity: 0 ou visibility: hidden durante a renderização no servidor. O servidor envia HTML invisível. O cliente hidrata, o JavaScript roda e o conteúdo aparece — ou pior, pisca entre estados.
O ReVue adota uma abordagem diferente:
- No servidor, os elementos renderizam normalmente, sem estado oculto.
- Após a hidratação, a diretiva aplica a classe inicial
reveale dispara a animação. - Usuários com
prefers-reduced-motion: reduceveem o conteúdo imediatamente, sem animação — a folha de estilo padrão trata essa media query.
O resultado é conteúdo sempre legível, mesmo se o JavaScript demorar a carregar ou falhar. O movimento é melhoria progressiva, não requisito para ver a página.
Estilização personalizada
Se o fade-and-slide padrão não combina com seu design system, desabilite o CSS embutido e traga o seu:
export default defineNuxtConfig({
modules: ['nuxt-revue'],
reVue: {
css: false,
},
})O ReVue continua definindo as custom properties CSS e alternando reveal / reveal--in. Você define os keyframes e o easing. O readme no npm inclui um exemplo completo com curva cubic-bezier personalizada e fallback para reduced motion — copie como ponto de partida e adapte.
Quando usar o ReVue
O ReVue encaixa em projetos que precisam de reveals leves no scroll e no mount sem adotar uma biblioteca completa como GSAP ou Motion One. É uma boa escolha para:
- Páginas de marketing e portfólios feitos com Nuxt
- Seções de conteúdo que se beneficiam de movimento sutil de entrada
- Times que preferem diretivas a componentes wrapper
- Projetos em que a correção de SSR é inegociável
Não é a ferramenta certa para animações complexas com timeline, movimento baseado em física ou interações por gesto. Para isso, use uma biblioteca dedicada e aceite o bundle maior e o trabalho extra de integração.
Experimente
O ReVue é open source sob licença MIT. Instale pelo npm, veja o código no GitHub e role pelo site de demo para ver defaults da app, diretivas sem opções e overrides locais funcionando juntos.
Se você constrói sites com Nuxt e está cansado de copiar plugins de scroll-reveal com gambiarras frágeis de SSR, vale testar o ReVue. Uma diretiva, defaults via config e animações que respeitam como o Nuxt realmente renderiza páginas.