ToolHub
View All Posts

Guida alle Animazioni CSS: Transizioni, Keyframe e Performance

Le animazioni CSS danno vita alle interfacce, fornendo feedback visivo, guidando l'attenzione dell'utente e creando esperienze memorabili. Fatte bene, le animazioni sembrano naturali e intuitive; fatte male, causano scatti, distraggono gli utenti e possono persino causare disagio fisico. Questa guida copre tutto, dalle basi di transizioni e keyframe fino all'ottimizzazione avanzata delle performance e all'accessibilità, dandoti le conoscenze per creare animazioni fluide, mirate e inclusive.

Transizioni CSS vs Animazioni

I CSS offrono due meccanismi distinti per creare effetti di movimento: transizioni e animazioni. Comprendere quando usare ciascuno è fondamentale per lavorare efficacemente con le animazioni CSS.

Transizioni CSS

Le transizioni animano il cambiamento tra due stati di una proprietà CSS. Definisci la proprietà da animare, la durata dell'animazione e la curva di easing, e il browser gestisce automaticamente l'interpolazione tra il valore iniziale e quello finale. Le transizioni sono attivate da cambiamenti di stato come hover, focus, aggiunta di classi o modifiche di proprietà via JavaScript.

.button {
  background: #3b82f6;
  transform: scale(1);
  transition: background 0.3s ease, transform 0.2s ease;
}

.button:hover {
  background: #2563eb;
  transform: scale(1.05);
}

Le transizioni sono ideali per semplici animazioni a due stati. Richiedono codice minimo, sono facili da comprendere e funzionano in modo affidabile su tutti i browser. La limitazione è che animano solo tra due valori — non puoi definire passaggi intermedi.

Animazioni CSS (Keyframe)

Le animazioni utilizzano la regola @keyframes per definire una sequenza di cambiamenti di stile in un numero arbitrario di passaggi. A differenza delle transizioni, le animazioni possono essere eseguite indipendentemente dai cambiamenti di stato, ripetersi all'infinito, riprodursi al contrario e mettersi in pausa. Ti danno un controllo preciso su ogni fotogramma dell'animazione.

@keyframes pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.8;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.pulse-element {
  animation: pulse 2s ease-in-out infinite;
}

Quando Usare Quale

ScenarioUsa TransizioneUsa Animazione
Effetto HoverNo
Stato FocusNo
Toggle VisibilitàForse
Sequenza Multi-stepNo
Animazione in LoopNo
Indipendente dallo StatoNo
Animazione di EntrataForse

Sintassi dei Keyframe in Profondità

La regola @keyframes è il cuore delle animazioni CSS. Comprendere a fondo la sua sintassi sblocca tutta la potenza delle sequenze di animazione a più passaggi.

Keyframe Basati su Percentuali

I keyframe sono definiti utilizzando valori percentuali da 0% a 100%, che rappresentano l'avanzamento sulla timeline dell'animazione. Puoi definire tutti i keyframe che desideri e il browser interpola tra di essi:

@keyframes bounce {
  0%, 100% {
    transform: translateY(0);
  }
  25% {
    transform: translateY(-20px);
  }
  50% {
    transform: translateY(0);
  }
  75% {
    transform: translateY(-10px);
  }
}

Più keyframe possono condividere lo stesso blocco di stili separando i valori percentuali con virgole, come 0%, 100% nell'esempio sopra. Questo è utile per animazioni che tornano allo stato iniziale.

Proprietà Abbreviata Animation

La proprietà abbreviata animation combina otto sotto-proprietà in una singola dichiarazione. L'ordine è: name, duration, timing-function, delay, iteration-count, direction, fill-mode e play-state.

.element {
  animation: slideIn 0.5s ease-out 0.2s 1 forwards running;
}

/* Equivalent longhand */
.element {
  animation-name: slideIn;
  animation-duration: 0.5s;
  animation-timing-function: ease-out;
  animation-delay: 0.2s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-play-state: running;
}

Modalità di Riempimento dell'Animazione

La proprietà animation-fill-mode controlla quali stili vengono applicati prima e dopo l'esecuzione dell'animazione. Questa è una delle proprietà di animazione più fraintese:

Funzioni di Easing

Le funzioni di easing (chiamate anche funzioni di timing) definiscono la curva di accelerazione dell'animazione. Determinano se l'animazione inizia lentamente e poi accelera, inizia velocemente e poi decelera, o segue un pattern più complesso. La giusta funzione di easing fa sembrare l'animazione naturale; quella sbagliata la fa sembrare meccanica o brusca.

Funzioni di Easing Incorporate

Curve di Bézier Cubiche

La funzione cubic-bezier() ti permette di definire curve di easing personalizzate con un controllo preciso. Accetta quattro parametri che rappresentano i punti di controllo di una curva di Bézier cubica: cubic-bezier(x1, y1, x2, y2). I valori x rappresentano il tempo (da 0 a 1), i valori y rappresentano l'avanzamento (possono superare 0-1 per effetti di overshoot).

.element {
  /* Smooth deceleration - great for entrances */
  transition: transform 0.3s cubic-bezier(0.0, 0.0, 0.2, 1.0);

  /* Smooth acceleration - great for exits */
  transition: transform 0.2s cubic-bezier(0.4, 0.0, 1, 1);

  /* Material Design standard easing */
  transition: transform 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
}

Funzioni a Gradini

La funzione steps() crea animazioni discrete fotogramma per fotogramma invece di un'interpolazione fluida. È utile per animazioni sprite o per creare un effetto "digitazione":

@keyframes typing {
  from { width: 0; }
  to { width: 100%; }
}

.typing-effect {
  animation: typing 3s steps(40, end);
  overflow: hidden;
  white-space: nowrap;
}

Ottimizzazione delle Performance

Animazioni fluide richiedono 60 fotogrammi al secondo (fps), il che significa che ogni fotogramma deve essere completato entro 16,67 millisecondi. Il mancato rispetto di questo budget causa scatti visibili — jank, fotogrammi persi e un'esperienza utente degradata. Comprendere la pipeline di rendering del browser è fondamentale per scrivere animazioni performanti.

Pipeline di Rendering

Quando una proprietà CSS cambia, il browser attraversa fino a tre fasi per aggiornare il display:

  1. Stile: determina quali regole CSS si applicano a quali elementi.
  2. Layout: calcola la dimensione e la posizione di ogni elemento. Attivato da cambiamenti di width, height, margin, padding, top, left, font-size e altre proprietà geometriche.
  3. Paint: riempie i pixel per ogni elemento. Attivato da cambiamenti di color, background, box-shadow, border-radius e altre proprietà visive.
  4. Compositing: combina i layer dipinti nell'ordine corretto. Solo questo passaggio viene eseguito sulla GPU. Attivato da cambiamenti di transform e opacity.

Le animazioni che attivano solo la fase di compositing hanno le migliori performance perché saltano completamente layout e paint. Ecco perché transform e opacity sono il gold standard per le animazioni CSS performanti.

Proprietà Solo Compositor

ProprietàAttiva Layout?Attiva Paint?Compositing GPU?
transformNoNo
opacityNoNo
filterNoA volte
top / leftNo
width / heightNo
margin / paddingNo
background-colorNoNo
box-shadowNoNo

Usare will-change

La proprietà will-change dice al browser quali proprietà ci si aspetta che cambino, permettendogli di ottimizzare in anticipo promuovendo l'elemento al proprio layer del compositor. Tuttavia, dovrebbe essere usata con cautela:

/* Apply will-change just before the animation */
.element:hover {
  will-change: transform;
}

/* Remove it after the animation completes */
.element {
  transition: transform 0.3s ease;
}

Gli errori comuni con will-change includono applicarlo a troppi elementi (ogni layer del compositor consuma memoria GPU) e mantenerlo permanentemente (spreca risorse). La buona pratica è aggiungere will-change via JavaScript appena prima dell'inizio dell'animazione e rimuoverlo al termine.

Usare Transform al Posto delle Proprietà di Layout

L'ottimizzazione delle performance più efficace è sostituire le proprietà che attivano il layout con transform:

Regola di Performance: se puoi ottenere lo stesso effetto visivo con transform o opacity, preferiscili sempre alle proprietà che attivano layout o paint. Questo principio da solo elimina la maggior parte dei problemi di performance delle animazioni.

Pattern di Animazione Comuni

Certi pattern di animazione appaiono ripetutamente nelle interfacce web. Padroneggiare questi pattern ti fornisce un toolkit per la maggior parte delle esigenze comuni di animazione UI.

1. Fade In

L'animazione di entrata più semplice e versatile. L'elemento passa da trasparente a opaco:

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.fade-in {
  animation: fadeIn 0.4s ease-out forwards;
}

2. Slide Up e Fade In

Un effetto di entrata più dinamico che combina movimento verticale e cambiamento di opacità. Crea la sensazione che l'elemento arrivi dal basso:

@keyframes slideUpFade {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.slide-up {
  animation: slideUpFade 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

3. Scala al Hover

Un sottile aumento di scala al hover fornisce un feedback interattivo soddisfacente:

.card {
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
  transform: translateY(-4px) scale(1.02);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}

4. Animazione a Scaglioni di Liste

Quando appare una lista di elementi, impostare ritardi di animazione scaglionati per ogni elemento crea un effetto a cascata che guida lo sguardo:

.list-item {
  opacity: 0;
  transform: translateY(10px);
  animation: slideUpFade 0.3s ease-out forwards;
}

.list-item:nth-child(1) { animation-delay: 0.0s; }
.list-item:nth-child(2) { animation-delay: 0.05s; }
.list-item:nth-child(3) { animation-delay: 0.1s; }
.list-item:nth-child(4) { animation-delay: 0.15s; }
.list-item:nth-child(5) { animation-delay: 0.2s; }

Per liste dinamiche, usa JavaScript per impostare l'animation-delay in base all'indice di ogni elemento, o usa proprietà personalizzate CSS: style="animation-delay: calc(var(--i) * 0.05s)".

5. Spinner di Caricamento

Una rotazione continua e fluida è il classico indicatore di caricamento:

@keyframes spin {
  to { transform: rotate(360deg); }
}

.spinner {
  width: 24px;
  height: 24px;
  border: 3px solid rgba(255, 255, 255, 0.2);
  border-top-color: #3b82f6;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

Accessibilità delle Animazioni: prefers-reduced-motion

Non tutti gli utenti traggono beneficio dalle animazioni. Per persone con disturbi vestibolari, sensibilità al movimento o certe condizioni cognitive, le animazioni possono causare vertigini, nausea o convulsioni. La media query prefers-reduced-motion ti permette di rispettare la preferenza di sistema dell'utente per la riduzione delle animazioni.

Implementare la Riduzione delle Animazioni

L'approccio raccomandato è abilitare le animazioni per gli utenti che non hanno impostato la preferenza di riduzione del movimento:

/* Default: no animation for users who prefer reduced motion */
.element {
  opacity: 1;
  transform: none;
}

/* Only animate for users who have no motion preference */
@media (prefers-reduced-motion: no-preference) {
  .element {
    animation: slideUpFade 0.5s ease-out forwards;
  }
}

In alternativa, puoi disabilitare animazioni specifiche per gli utenti che preferiscono la riduzione del movimento:

.element {
  animation: slideUpFade 0.5s ease-out forwards;
}

@media (prefers-reduced-motion: reduce) {
  .element {
    animation: none;
    opacity: 1;
    transform: none;
  }

  /* Keep functional transitions but shorten duration */
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Cosa Mantenere e Cosa Rimuovere

Quando l'utente preferisce la riduzione del movimento, non tutte le animazioni dovrebbero essere rimosse. Le animazioni funzionali che comunicano significato o stato dovrebbero essere mantenute, solo semplificate:

Librerie di Animazione

Sebbene le animazioni CSS gestiscano la maggior parte delle esigenze UI, le librerie di animazione JavaScript offrono funzionalità avanzate come il movimento basato sulla fisica, animazioni legate allo scroll e orchestrazione di sequenze complesse.

Librerie CSS-first

Librerie di Animazione JavaScript

Quando Usare JavaScript vs CSS

CSS per animazioni dichiarative semplici che rispondono a cambiamenti di stato. JavaScript per: movimento basato sulla fisica (molle, momentum), animazioni legate allo scroll, sequenze complesse con controllo temporale preciso, parametri di animazione dinamici calcolati a runtime, o animazioni che devono essere messe in pausa, invertite o trascinate programmaticamente.

Debug delle Animazioni

I bug delle animazioni possono essere sottili e difficili da diagnosticare. Gli strumenti e le tecniche di debug giusti rendono il processo molto più efficiente.

Pannello Animazioni di Chrome DevTools

Chrome DevTools include un pannello Animazioni dedicato che fornisce potenti funzionalità di debug:

Analisi delle Performance

Usa il pannello Performance in Chrome DevTools per identificare gli scatti nelle animazioni:

Scenari Comuni di Debug

Lavori con i CSS? Prova i nostri strumenti CSS gratuiti per formattare, minimizzare e ottimizzare i tuoi fogli di stile per la produzione.

Formattatore CSSMinificatore CSS

Domande Frequenti

Dovrei usare transizioni CSS o animazioni CSS?

Le transizioni CSS sono per semplici cambiamenti di stato dal punto A al punto B, come effetti hover, stati focus e toggle di visibilità. Le animazioni CSS (keyframe) sono per sequenze complesse a più passaggi, animazioni in loop o animazioni che devono essere eseguite indipendentemente dai cambiamenti di stato. Le transizioni sono più semplici; le animazioni offrono più controllo.

Quali proprietà CSS sono sicure da animare per le performance?

Le proprietà con le migliori performance per le animazioni sono transform e opacity, perché possono essere gestite interamente dal compositor GPU senza attivare layout o paint. Altre proprietà come width, height, margin e top attivano il ricalcolo del layout, che è costoso. Preferisci sempre transform: translateX() a left, e transform: scale() ai cambiamenti di width/height.

Come rendere le animazioni accessibili per utenti sensibili?

Usa la media query prefers-reduced-motion per disabilitare o semplificare le animazioni per gli utenti che hanno attivato l'impostazione "Riduci movimento" nel sistema operativo. Avvolgi le animazioni non essenziali in @media (prefers-reduced-motion: no-preference) e fornisci cambiamenti di stato istantanei come fallback per gli utenti che preferiscono la riduzione del movimento.

Cos'è will-change e quando dovrei usarlo?

will-change è una proprietà CSS che suggerisce al browser quali proprietà cambieranno in futuro, permettendogli di ottimizzare in anticipo. Usalo con parsimonia, solo quando osservi problemi di performance. Applicalo prima dell'inizio dell'animazione e rimuovilo al termine. L'uso eccessivo di will-change spreca memoria GPU e può effettivamente danneggiare le performance.

Come fare il debug delle animazioni CSS?

Chrome DevTools offre potenti strumenti di debug per le animazioni. Apri il pannello Animazioni (nel menu Altri strumenti) per visualizzare tutte le animazioni attive, trascinare la timeline, modificare durata e ritardo in tempo reale e rallentare le animazioni a 1/4 della velocità. Puoi anche usare il pannello Performance per identificare scatti nelle animazioni e layout thrashing.