Capitolo 11 di 11

Tutorial VueJS 3: transizioni e animazioni con Transition

verificato il 2 Settembre 2026 · 5 min

Risposta rapida

<Transition> anima un singolo elemento quando compare e quando sparisce, <TransitionGroup> anima una lista. Vue applica classi CSS, il vostro foglio di stile decide l’effetto. Attenzione: in Vue 3 le classi di partenza sono -enter-from e -leave-from, non -enter e -leave come in Vue 2.

Alla fine di questo capitolo, saprete animare la comparsa, la sparizione e lo spostamento di elementi, senza librerie.

Un elemento che compare di colpo produce un effetto di scatto. Vue offre due componenti integrati, <Transition> e <TransitionGroup>, che applicano classi CSS al momento giusto per animare le entrate e le uscite. Nessuna libreria da installare.

Il principio

Avvolgete in <Transition> un elemento la cui visualizzazione dipende da una condizione. Vue non lo anima da sé: aggiunge e toglie classi, ed è il vostro CSS a decidere l’effetto.

Sei classi coprono l’intero ciclo.

css
/* entrata */
.v-enter-from     /* stato di partenza, applicato appena prima dell’inserimento */
.v-enter-active   /* per tutta l’entrata: è qui che va transition */
.v-enter-to       /* stato di arrivo */

/* uscita */
.v-leave-from     /* stato di partenza dell’uscita */
.v-leave-active   /* per tutta l’uscita */
.v-leave-to       /* stato finale, appena prima della rimozione dal DOM */

Il prefisso v- è quello di una transizione senza nome. Con name="fade", le classi diventano fade-enter-from, fade-enter-active, e così via.

La trappola del codice trovato sul web

In Vue 2 le classi di partenza si chiamavano .fade-enter e .fade-leave, senza suffisso. Vue 3 le ha rinominate in -enter-from e -leave-from. Un esempio copiato da un articolo vecchio non produrrà quindi alcuna animazione in entrata, senza il minimo messaggio di errore. Se la vostra transizione non fa nulla, verificate prima questo punto.

Animare la disponibilità

In ProductDisplay.vue, il messaggio di disponibilità passa da un paragrafo all’altro a seconda della variante sotto il puntatore. Avvolgeteli:

src/components/ProductDisplay.vue
<Transition name="fade" mode="out-in">
  <p v-if="inStock" key="in">En stock</p>
  <p v-else key="out">En rupture</p>
</Transition>

Poi descrivete l’effetto nel foglio di stile, come nel capitolo sulle classi e gli stili:

src/assets/boutique.css
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
  transform: translateY(-10px);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity .3s ease, transform .3s ease;
}

Passate sopra ai pallini: il messaggio sfuma invece di scattare.

mode="out-in" attende che l’elemento vecchio sia uscito prima di inserire quello nuovo. Senza, i due paragrafi coesistono per una frazione di secondo e si sovrappongono.

Che cosa accetta Transition

Un solo elemento alla volta. È il vincolo principale: <Transition> anima un unico figlio, non una lista.

Si attiva in tre situazioni: un v-if, un v-show, oppure un cambio di componente via <component :is>. Per forzare una transizione fra due elementi dello stesso tipo, dategli key diverse, come sopra.

Animare una lista

Per una lista serve <TransitionGroup>. Due differenze: accetta più figli e rende esso stesso un elemento contenitore se glielo chiedete con tag.

In ReviewList.vue, sostituite il <ul>:

src/components/ReviewList.vue
<template>
  <div class="review-container">
    <h3>Avis</h3>
    <TransitionGroup name="liste" tag="ul">
      <li v-for="review in reviews" :key="review.id">
        {{ review.name }} a mis {{ review.rating }} étoiles
        <br>
        « {{ review.review }} »
      </li>
    </TransitionGroup>
  </div>
</template>

Ogni figlio ha bisogno di una key unica e stabile. L’indice qui non va bene: cambia a ogni inserimento, e Vue non saprebbe più quale elemento è nuovo. Diamo un identificatore a ogni recensione al momento dell’aggiunta:

src/components/ProductDisplay.vue
<script setup>
function addReview(review) {
  reviews.value.push({ ...review, id: crypto.randomUUID() })
}
</script>

crypto.randomUUID() è disponibile in tutti i browser aggiornati, sulle pagine servite in HTTPS o da localhost.

Il CSS aggiunge una classe in più, -move, che anima lo spostamento degli elementi rimasti quando un vicino sparisce:

src/assets/boutique.css
.liste-enter-from,
.liste-leave-to {
  opacity: 0;
  transform: translateX(24px);
}

.liste-enter-active,
.liste-leave-active,
.liste-move {
  transition: all .3s ease;
}

Inviate più recensioni: ognuna entra scorrendo, e le altre si riorganizzano dolcemente.

Uscita e spostamento

Perché -move funzioni alla rimozione, l’elemento che esce deve essere tolto dal flusso, altrimenti gli altri si muovono solo alla fine della sua animazione. Aggiungete position: absolute alla classe -leave-active quando i vostri elementi sono eliminabili.

Animare alla prima visualizzazione

Per impostazione predefinita, nulla viene animato al rendering iniziale. L’attributo appear cambia le cose:

html
<Transition name="fade" appear>
  <p>Visible dès le chargement, en fondu</p>
</Transition>

Le animazioni CSS e gli hook

transition non è l’unica opzione: funziona anche una animation CSS, applicata sulla classe -enter-active.

Per pilotare una libreria di animazione in JavaScript, <Transition> emette eventi a ogni tappa:

html
<Transition
  :css="false"
  @before-enter="avantEntree"
  @enter="entree"
  @after-enter="apresEntree"
  @leave="sortie"
>
  <p v-if="visible">Contenu</p>
</Transition>

Con :css="false", Vue smette di gestire le classi e vi lascia il comando. Le funzioni enter e leave ricevono allora l’elemento e una callback done da chiamare quando l’animazione è finita:

javascript
function entree(el, done) {
  // animazione con la libreria che preferite
  done()
}

Il movimento non è sempre desiderabile

Alcune persone disattivano le animazioni a livello di sistema, in particolare per evitare la nausea legata al movimento. Rispettate questa impostazione:

src/assets/boutique.css
@media (prefers-reduced-motion: reduce) {
  .fade-enter-active,
  .fade-leave-active,
  .liste-enter-active,
  .liste-leave-active,
  .liste-move {
    transition: none;
  }
}

L’interfaccia resta funzionante, sparisce solo l’animazione.

È la fine del tutorial

La vostra applicazione mostra un prodotto e le sue varianti, gestisce un carrello, valida un modulo e anima i suoi cambi di stato. Avete coperto la reattività, le direttive, i componenti, le props, gli eventi e le transizioni: quanto basta per leggere e scrivere Vue tutti i giorni.

Per il seguito, due direzioni. La condivisione dello stato fra componenti lontani con Pinia, quando far risalire gli eventi diventa faticoso. E il routing con Vue Router, appena l’applicazione ha più pagine.

Con la Options API

<Transition> e <TransitionGroup> sono componenti integrati: si scrivono esattamente allo stesso modo. Cambiano posto solo le funzioni degli hook JavaScript, che finiscono nell’opzione methods.

EsercizioAggiungete una transizione sull’immagine del prodotto perché sfumi al cambio di variante. Vi servirà una key legata alla variante selezionata.

Errori frequenti

Usare le classi di Vue 2 .fade-enter e .fade-leave sono state rinominate in -enter-from e -leave-from. Non si anima nulla e non compare alcun errore.
Dimenticare mode="out-in" Senza, l’elemento che entra e quello che esce coesistono per una frazione di secondo e si sovrappongono.
Usare l’indice come chiave in un TransitionGroup Vue non riesce più a distinguere l’elemento nuovo dagli altri e anima la voce sbagliata.
Testare un componente animato con Vue Test Utils Le transizioni sono sostituite da stub per impostazione predefinita. Passate global: { stubs: { 'transition-group': false } } per osservare il rendering reale.
Newsletter

I nuovi test, tutorial e progetti, via e-mail.

Test riproducibili, codice versionato, risultati datati. Mai spam.