Vue.js: Transições e Animações
Última atualização: 2026-08-26
As transições e animações tornam seu aplicativo Vue mais dinâmico — transições suaves à medida que os elementos entram ou saem da área de exibição e um reajuste elegante à medida que as listas mudam. O Vue inclui os componentes <Transition> e <TransitionGroup>, que funcionam com nomes de classes CSS ou hooks de JavaScript para obter vários efeitos de animação.
Dominar as animações de transição é fundamental para melhorar a experiência do usuário — boas animações fazem com que um aplicativo pareça “fluido, ágil e profissional”.
1. O que você vai aprender
<Transition>Animação de entrada/saída de um único elemento- 6 ganchos de classe CSS (v-enter-from / v-enter-active etc.)
<TransitionGroup>Animação da lista- Hooks do JavaScript (@before-enter / @enter etc.)
- Integração de bibliotecas de animação de terceiros (@vueuse/motion, GSAP)
- Integração com o Animate.css
- 5 cenários-chave do mundo real
2. O incômodo de um botão físico para “mudar de aba”
(1) Problema: Componentes desaparecem ou aparecem repentinamente; a interface do usuário pisca
O painel de administração do Alice tinha um seletor de abas:
<!-- ❌ The "Broken" Version:v-if Sudden Switch -->
<template>
<button @click="currentTab = 'home'">Home</button>
<button @click="currentTab = 'profile'">Profile</button>
<div v-if="currentTab === 'home'">Home Content</div>
<div v-else-if="currentTab === 'profile'">Profile Content</div>
</template>
Experiência do usuário:
- Aparece/desaparece repentinamente ao alternar entre abas
- Não há animações de transição, o que dá uma sensação de “desconforto”.
- Falta de profissionalismo
(2) Solução para transições no Vue: 1 tag, 6 classes
<!-- ✅ Correct Version:Smooth Transition -->
<template>
<button @click="currentTab = 'home'">Home</button>
<button @click="currentTab = 'profile'">Profile</button>
<Transition name="fade" mode="out-in">
<div v-if="currentTab === 'home'" key="home">Home Content</div>
<div v-else-if="currentTab === 'profile'" key="profile">Profile Content</div>
</Transition>
</template>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
Experiência do usuário:
- Fade-in e fade-out suaves ao alternar entre abas
- Transição de 0,3 segundo, conferindo um aspecto profissional
- 6 classes CSS aplicadas automaticamente
(3) Receita
Após adicionar as transições:
- Experiência do usuário: De “desajeitada” a “fluida”
- Profissionalismo: Melhorou significativamente
- Volume do código: 1 tag
<Transition>+ 6 classes CSS - Personalizável: 4 nomes de transição + 3 modos
3. Transição: Elemento Único
(1) Uso básico
<template>
<button @click="show = !show">Toggle</button>
<Transition name="fade">
<p v-if="show">Hello Vue</p>
</Transition>
</template>
<style>
/* 6 CSS classes, Vue Auto-add/Remove */
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
(2) Uma explicação detalhada sobre 6 classes CSS
| Classe | Condição de acionamento | Finalidade |
|---|---|---|
v-enter-from |
Antes da inserção do elemento | Estado inicial |
v-enter-active |
Todo o processo de inserção de elementos | Processo de transição |
v-enter-to |
Após inserir um elemento | Estado final |
v-leave-from |
Antes de o elemento sair | Estado inicial |
v-leave-active |
O elemento sai de todo o processo | Processo de transição |
v-leave-to |
Depois que o elemento sai | Estado final |
(3) Convenções de nomenclatura
<!-- v-bind:name="fade" → 6 classes are .fade-xxx -->
<Transition name="fade">...</Transition>
<!-- Don't write name → Default v-xxx (6 classes are .v-xxx) -->
<Transition>...</Transition>
<!-- News name -->
<Transition :name="transitionName">...</Transition>
(4) 3 modos
<!-- 1. Default Mode:Entry and exit occur simultaneously(Overlap) -->
<Transition name="fade">
<div v-if="show">Content</div>
</Transition>
<!-- 2. out-in:Leave first, then enter(Recommendations,Avoid Overlapping) -->
<Transition name="fade" mode="out-in">
<div v-if="show">Content</div>
</Transition>
<!-- 3. in-out:Enter first, then leave(Rare) -->
<Transition name="fade" mode="in-out">
<div v-if="show">Content</div>
</Transition>
4. 5 tipos de animações CSS
(1) Fade In e Fade Out (os mais comuns)
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
(2) Deslizamento
.slide-enter-active, .slide-leave-active {
transition: transform 0.3s;
}
.slide-enter-from {
transform: translateX(-100%);
}
.slide-leave-to {
transform: translateX(100%);
}
(3) Zoom
.scale-enter-active, .scale-leave-active {
transition: transform 0.3s;
}
.scale-enter-from, .scale-leave-to {
transform: scale(0);
}
(4) Rotação
.rotate-enter-active {
transition: transform 1s;
}
.rotate-enter-from {
transform: rotate(0deg);
}
.rotate-leave-active {
animation: bounce 0.5s;
}
@keyframes bounce {
0% { transform: scale(0); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
(5) Animação composta
.combo-enter-active, .combo-leave-active {
transition: all 0.3s;
}
.combo-enter-from {
opacity: 0;
transform: translateX(-50px) scale(0.8);
}
.combo-leave-to {
opacity: 0;
transform: translateX(50px) scale(0.8);
}
5. Animações de transição em listas de grupos
(1) Uso básico
<template>
<button @click="add">Add</button>
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.name }}
<button @click="remove(item.id)">×</button>
</li>
</TransitionGroup>
</template>
<script setup>
import { ref } from 'vue'
const items = ref([
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' }
])
function add() {
const id = Date.now()
items.value.push({ id, name: `Item ${id}` })
}
function remove(id) {
items.value = items.value.filter(i => i.id !== id)
}
</script>
<style>
/* 6 classes, However, for list items, enter/leave/move */
.list-enter-active, .list-leave-active {
transition: all 0.5s;
}
.list-enter-from, .list-leave-to {
opacity: 0;
transform: translateX(30px);
}
.list-leave-active {
position: absolute; /* Remove from the document flow when leaving */
}
/* Animation when list items move */
.list-move {
transition: transform 0.5s;
}
</style>
(2) Ponto-chave: .list-move
/* When the position of a list item changes(As sorted),Apply Automatically .list-move */
.list-move {
transition: transform 0.5s;
}
(3) 5 principais cenários de animação de listas
| Cena | Animação |
|---|---|
| Adicionar item | Entrada com efeito de desvanecimento + deslizamento para baixo |
| Excluir item | Desaparecer gradualmente + deslizar para a esquerda |
| Ordenar | Mover suavemente para a nova posição |
| Filtro | Desvanecimento para itens que estão sendo removidos, transição suave para itens que estão sendo mantidos |
| Arrastar | Seguir o mouse em tempo real |
6. Hooks do JavaScript
(1) 8 ganchos de JavaScript
<template>
<Transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
:css="false" <!-- Disable CSS class -->
>
<p v-if="show">Hello</p>
</Transition>
</template>
<script setup>
import gsap from 'gsap'
function beforeEnter(el) {
console.log('Before enter:', el)
}
function enter(el, done) {
gsap.to(el, {
opacity: 1,
y: 0,
duration: 0.5,
onComplete: done // Notification Complete
})
}
function afterEnter(el) {
console.log('After enter:', el)
}
// leave / beforeLeave / afterLeave Similar
</script>
(2) Integração com o GSAP (recomendado)
npm install gsap
<template>
<Transition :css="false" @enter="onEnter" @leave="onLeave">
<p v-if="show">Hello GSAP</p>
</Transition>
</template>
<script setup>
import gsap from 'gsap'
function onEnter(el, done) {
gsap.fromTo(el,
{ opacity: 0, y: 50 },
{ opacity: 1, y: 0, duration: 0.5, onComplete: done }
)
}
function onLeave(el, done) {
gsap.to(el, { opacity: 0, y: -50, duration: 0.3, onComplete: done })
}
</script>
7. Bibliotecas de animação de terceiros
(1) Integração com o Animate.css
npm install animate.css
// main.js
import 'animate.css'
<template>
<Transition
enter-active-class="animate__animated animate__fadeIn"
leave-active-class="animate__animated animate__fadeOut"
>
<p v-if="show">Hello</p>
</Transition>
</template>
(2) @vueuse/motion
npm install @vueuse/motion
// main.js
import { MotionPlugin } from '@vueuse/motion'
app.use(MotionPlugin)
<template>
<div v-motion :initial="{ opacity: 0, y: 50 }" :enter="{ opacity: 1, y: 0 }">
Fade in from below
</div>
</template>
(3) Casos de uso recomendados para o GSAP
| Biblioteca | Classificação | Indicado para |
|---|---|---|
| Animações CSS | ⭐⭐⭐⭐⭐ | Transições simples, efeitos de desvanecimento |
| Animate.css | ⭐⭐⭐⭐ | Uma ampla variedade de animações predefinidas |
| @vueuse/motion | ⭐⭐⭐⭐ | Declarativo, integra-se bem com o Vue |
| GSAP | ⭐⭐⭐⭐⭐ | Linhas do tempo complexas, animações baseadas na física |
8. Exemplos completos: 5 principais cenários de transição
▶ Exemplo: 1. 5 tipos de animações CSS
/* 1. Fade In, Fade Out */
.fade-enter-active, .fade-leave-active { transition: opacity 0.3s; }
.fade-enter-from, .fade-leave-to { opacity: 0; }
/* 2. Slide */
.slide-enter-active, .slide-leave-active { transition: transform 0.3s; }
.slide-enter-from { transform: translateX(-100%); }
.slide-leave-to { transform: translateX(100%); }
/* 3. Zoom */
.scale-enter-active, .scale-leave-active { transition: transform 0.3s; }
.scale-enter-from, .scale-leave-to { transform: scale(0); }
/* 4. Rotation */
.rotate-enter-active { transition: transform 1s; }
.rotate-enter-from { transform: rotate(0deg); }
.rotate-leave-active { animation: spin 0.5s; }
/* 5. Combination */
.combo-enter-active, .combo-leave-active { transition: all 0.3s; }
.combo-enter-from { opacity: 0; transform: translateX(-50px) scale(0.8); }
▶ Exemplo: 2. Explicação detalhada de 6 classes CSS
| Classe | Gatilho |
|---|---|
.fade-enter-from |
Antes de inserir um elemento |
.fade-enter-active |
Processo de inserção de elementos |
.fade-enter-to |
Após inserir o elemento |
.fade-leave-from |
Antes que o Elemento se vá |
.fade-leave-active |
Processo de saída de elementos |
.fade-leave-to |
Depois que o Elemento Partiu |
▶ Exemplo: 3. Animação de lista com TransitionGroup
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</TransitionGroup>
<style>
.list-enter-active, .list-leave-active {
transition: all 0.5s;
}
.list-move { transition: transform 0.5s; }
</style>
▶ Exemplo: 4. 5 Principais bibliotecas de animação de terceiros
| Biblioteca | Comando | Aplicável |
|---|---|---|
| CSS | Nenhum (integrado) | Simples |
| Animate.css | npm i animate.css |
Animações predefinidas |
| @vueuse/motion | npm i @vueuse/motion |
Declarativo |
| GSAP | npm i gsap |
Linha do tempo complexa |
| Motion One | npm i motion |
Animação leve para a web |
▶ Exemplo: 5. Referência rápida para 5 erros comuns
| Erro | Sintoma | Solução |
|---|---|---|
| A transição não é aplicada | O elemento desaparece imediatamente | Adicionar o wrapper <Transition> + v-if |
| v-for sem animação | sem transições entre os itens da lista | usando <TransitionGroup> |
| Não há animação ao classificar | Movimentos irregulares | Adicionar a classe .list-move |
| Comutação simultânea entre vários componentes | Sobreposição | Adicionar key para distinguir + mode="out-in" |
| As animações CSS são muito rápidas/muito lentas | Experiência do usuário insatisfatória | Ajuste a duração da transição para 0,2–0,5 s |
▶ Exemplo: 6. 5 Cenários práticos
| Cena | Animação |
|---|---|
| Alternância de abas | fade + de fora para dentro |
| Caixa de diálogo modal | ampliar + esmaecer |
| Adicionar/Remover da lista | Animação da lista |
| Mudança de rota | fade + slide |
| Notificação pop-up | desliza do topo + fechamento automático |
❓ Perguntas Frequentes
P: Como faço para escolher entre transições CSS e @keyframes CSS? R: Use transições CSS para transições simples (opacidade/transformação). Use @keyframes ou GSAP para animações complexas (em várias etapas, baseadas em física). O Vue Transitions oferece suporte a ambas.
P: O TransitionGroup exige o seletor :key? R: Sim.
<TransitionGroup>Os elementos filhos devem ser identificados de forma exclusiva usando:key; caso contrário, a animação não será acionada.
P: Como faço para implementar uma animação de “transição de página”? R: Coloque-a entre
<router-view v-slot="{ Component }">+<Transition>. Sempre que a rota mudar, o componente será atualizado, acionando uma transição.
P: Qual é a finalidade de
mode="out-in"?R: Ele garante que o componente que está saindo conclua sua animação antes que o componente que está entrando comece. Isso evita que os dois componentes sejam exibidos ao mesmo tempo (sobrepondo-se).
P: É possível usar hooks de JavaScript e classes CSS juntos? R: Sim.
<Transition :css="false" @enter="onEnter">Desative as classes CSS e use apenas hooks de JavaScript. Ou ative ambos (use classes CSS para estilização e hooks de JavaScript para callbacks).
P: O que posso fazer se as animações estiverem lentas? R: (1) Use
transformeopacity(aceleradas por GPU); (2) Evite propriedades que acionem o layout (width, height, top); (3) Reduza o número de elementos que estão sendo animados simultaneamente.
P: Como faço para usar o Animate.css com o Vue? R: Use
enter-active-class="animate__animated animate__fadeIn"para mapear os nomes das classes do Animate.css para os hooks do Vue.
📖 Resumo
<Transition>Adiciona ou remove um único elemento; 6 classes CSS são gerenciadas automaticamente<TransitionGroup>Animação da lista,.list-moveClassificação- 3 modos: Padrão (sobreposto) / de fora para dentro (recomendado) / de dentro para fora
- 5 tipos de animações CSS: Fade In/Out / Deslizamento / Escala / Rotação / Combinação
- 8 ganchos do JS: before-enter / enter / after-enter / before-leave / leave / after-leave
- 5 principais bibliotecas de terceiros: CSS / Animate.css / @vueuse/motion / GSAP / Motion One
- 5 exercícios práticos: alternância entre abas / janelas modais / listas / roteamento / notificações
📝 Exercícios
-
Questões básicas (Dificuldade: ⭐)
Implemente um modal simples com efeito de fade-in/fade-out:
- Clique no botão para abrir a janela modal
- Fade in em 0,3 segundos
- Clique para fechar (desaparecer gradualmente)
- Fade-in e fade-out sincronizados da máscara de fundo
-
Problemas avançados (Dificuldade: ⭐⭐)
Implementar uma animação de lista com o TransitionGroup:
- 5 tarefas a fazer
- Entrada gradual do novo item (0,5 segundos)
- Fazer os itens excluídos desaparecerem gradualmente (0,5 segundos + position: absolute)
- Outros itens se movem suavemente durante a classificação (.list-move)
-
Problema desafiador (Dificuldade: ⭐⭐⭐)
Implementar um sistema completo de “animação de transição de página”:
- Animação de fade + deslizamento ao alternar entre rotas
- Três tipos de animações para adicionar, excluir e ordenar itens em uma lista
- A combinação “scale + fade” para janelas pop-up modais
- Animações complexas de linha do tempo com integração ao GSAP
- Teste comparativo de 5 bibliotecas de animação de terceiros
- Otimização de desempenho (aceleração por GPU + a ser alterado)