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
| Scenario | Usa Transizione | Usa Animazione |
|---|---|---|
| Effetto Hover | Sì | No |
| Stato Focus | Sì | No |
| Toggle Visibilità | Sì | Forse |
| Sequenza Multi-step | No | Sì |
| Animazione in Loop | No | Sì |
| Indipendente dallo Stato | No | Sì |
| Animazione di Entrata | Forse | Sì |
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:
- none (predefinito): al termine dell'animazione, l'elemento torna allo stile precedente all'animazione.
- forwards: dopo l'animazione, l'elemento mantiene lo stile dell'ultimo fotogramma. Essenziale per le animazioni di entrata in cui l'elemento deve rimanere nella posizione finale.
- backwards: durante il ritardo dell'animazione (prima che inizi), l'elemento applica lo stile del primo fotogramma.
- both: combina i comportamenti forwards e backwards. L'elemento mostra il primo fotogramma durante il ritardo e mantiene l'ultimo fotogramma al completamento.
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
- linear: velocità costante per tutta l'animazione. Raramente sembra naturale perché gli oggetti nel mondo reale non si muovono a velocità costante. Adatto per animazioni meccaniche o di rotazione.
- ease (predefinito): inizia lentamente, accelera a metà e decelera alla fine. Un buon easing generico per la maggior parte delle transizioni UI.
- ease-in: inizia lentamente e poi accelera. Crea una sensazione di "accumulo di slancio". Adatto per elementi che escono dallo schermo o cadono.
- ease-out: inizia velocemente e poi decelera. Crea una sensazione di "arrivo". L'easing più comunemente usato per gli elementi UI che entrano nello schermo.
- ease-in-out: inizia e finisce lentamente, più veloce a metà. Simile a ease ma con accelerazione e decelerazione più pronunciate. Adatto per transizioni più ampie e drammatiche.
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:
- Stile: determina quali regole CSS si applicano a quali elementi.
- 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.
- Paint: riempie i pixel per ogni elemento. Attivato da cambiamenti di color, background, box-shadow, border-radius e altre proprietà visive.
- 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? |
|---|---|---|---|
| transform | No | No | Sì |
| opacity | No | No | Sì |
| filter | No | Sì | A volte |
| top / left | Sì | Sì | No |
| width / height | Sì | Sì | No |
| margin / padding | Sì | Sì | No |
| background-color | No | Sì | No |
| box-shadow | No | Sì | No |
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:
- Usa transform: translateX(100px) invece di left: 100px
- Usa transform: translateY(50px) invece di top: 50px
- Usa transform: scale(1.5) invece di width: 150%; height: 150%
- Usa transform: rotate(45deg) invece di rotazione via layout
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:
- Rimuovi: animazioni decorative, parallax scrolling, caroselli a riproduzione automatica, effetti pulse e animazioni di sfondo in loop.
- Semplifica: le durate delle transizioni dovrebbero essere ridotte a quasi istantanee (0,01ms) invece di essere completamente rimosse, così che i cambiamenti di stato rimangano percepibili.
- Mantieni: transizioni di stato funzionali (hover, focus, active), indicatori di progresso e qualsiasi animazione che comunichi informazioni importanti.
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
- Animate.css: una raccolta di classi di animazione CSS predefinite. Basta aggiungere nomi di classe agli elementi per applicare le animazioni. Ottimo per prototipazione rapida ma può portare a effetti generici se abusato.
- Hamburgers: una raccolta di transizioni di icone menu hamburger animate, tutte implementate in puro CSS.
Librerie di Animazione JavaScript
- Framer Motion: libreria di animazione React che offre API dichiarative con supporto per fisica a molla, animazioni di layout e gesti. La scelta migliore per le app React.
- GSAP (GreenSock): la libreria di animazione JavaScript più potente. Offre controllo preciso della timeline, easing complessi, morphing SVG e animazioni attivate dallo scroll. Utilizzata dai grandi marchi per siti di marketing ed esperienze interattive.
- Anime.js: libreria di animazione JavaScript leggera con un'API pulita. Supporta proprietà CSS, SVG, attributi DOM e oggetti JavaScript. Una buona via di mezzo tra CSS e GSAP.
- Motion One: libreria di animazione moderna e leggera costruita sulla Web Animations API. Offre un'API minimale con supporto per fisica a molla e timeline.
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:
- Vista Timeline: visualizza tutte le animazioni attive sulla pagina con le loro durate, ritardi e keyframe.
- Controlli di Riproduzione: rallenta le animazioni a 1/4 di velocità, mettile in pausa o trascina la timeline fotogramma per fotogramma.
- Ispezione delle Proprietà: clicca su un'animazione nella timeline per vedere le esatte proprietà CSS animate e i loro valori a ogni keyframe.
- Modifica in Tempo Reale: modifica durata, ritardo ed easing delle animazioni in tempo reale senza ricaricare la pagina.
Analisi delle Performance
Usa il pannello Performance in Chrome DevTools per identificare gli scatti nelle animazioni:
- Registra una traccia delle performance mentre l'animazione è in esecuzione
- Cerca fotogrammi che superano il budget di 16,67ms (mostrati come barre rosse nel grafico dei fotogrammi)
- Controlla se ci sono operazioni di "Layout" nei fotogrammi dell'animazione, che indicano proprietà che attivano il layout
- Usa la scheda "Rendering" per attivare "Paint flashing" (mostra le aree ridipinte in verde) e "Layer borders" (mostra i layer del compositor)
Scenari Comuni di Debug
- Animazione non in esecuzione: controlla se animation-fill-mode è impostato correttamente. Senza forwards o both, l'elemento torna allo stato pre-animazione. Verifica anche che l'elemento abbia dimensioni corrette — transform: scale(0) rende l'elemento invisibile ma ancora presente.
- Animazione scattosa: apri il pannello Performance e cerca fotogrammi lunghi. Controlla se stai animando proprietà che attivano il layout. Passa a transform e opacity.
- Il ritardo dell'animazione non sembra corretto: ricorda che animation-delay crea un intervallo prima dell'inizio dell'animazione. Durante questo intervallo, l'elemento mostra lo stato pre-animazione a meno che non sia impostato animation-fill-mode: backwards o both.
- L'animazione funziona in Chrome ma non in Safari: Safari ha un parsing più restrittivo della proprietà abbreviata animation. Assicurati che tutti i valori siano nell'ordine corretto e che non stai utilizzando funzionalità non supportate.
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 CSSDomande 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.