Immagina questo: ti unisci a un nuovo progetto, ti immergi nella base di codice e nelle prime ore scopri qualcosa di frustrantemente familiare. Sparse tra i fogli di stile, trovi più definizioni @keyframes per le stesse animazioni di base. Tre diversi effetti di dissolvenza in apertura, due o tre variazioni di diapositive, una manciata di animazioni di zoom e almeno due diverse animazioni di rotazione perché, beh, perché no? @impulso fotogrammi chiave { da { scala: 1; } a { scala: 1.1; } }
@keyframes impulso più grande { 0%, 20%, 100% { scala: 1; } 10%, 40% { scala: 1,2; } }
Se questo scenario ti sembra familiare, non sei solo. Nella mia esperienza in vari progetti, una delle soluzioni rapide più costanti che posso ottenere è il consolidamento e la standardizzazione dei fotogrammi chiave. È diventato uno schema così affidabile che ora attendo con ansia questa pulizia come uno dei miei primi compiti su qualsiasi nuova base di codice. La logica dietro il caos Questa ridondanza ha perfettamente senso se ci pensi. Usiamo tutti le stesse animazioni fondamentali nel nostro lavoro quotidiano: dissolvenze, diapositive, zoom, rotazioni e altri effetti comuni. Queste animazioni sono piuttosto semplici ed è facile creare una rapida definizione di @keyframes per portare a termine il lavoro. Senza un sistema di animazione centralizzato, gli sviluppatori scrivono naturalmente questi fotogrammi chiave da zero, ignari del fatto che animazioni simili esistono già altrove nel codice base. Ciò è particolarmente comune quando si lavora su architetture basate su componenti (cosa che la maggior parte di noi fa oggigiorno), poiché i team spesso lavorano in parallelo su diverse parti dell'applicazione. Il risultato? Caos dell'animazione. Il piccolo problema I problemi più evidenti con la duplicazione dei fotogrammi chiave sono lo spreco di tempo di sviluppo e l'inutile ingrossamento del codice. Più definizioni di fotogrammi chiave significano più posizioni da aggiornare quando i requisiti cambiano. Hai bisogno di regolare i tempi dell'animazione di dissolvenza? Dovrai scovare ogni istanza nella tua base di codice. Vuoi standardizzare le funzioni di allentamento? Buona fortuna nel trovare tutte le varianti. Questa moltiplicazione dei punti di manutenzione rende anche i semplici aggiornamenti delle animazioni un'attività dispendiosa in termini di tempo. Il problema più grande Questa duplicazione dei fotogrammi chiave crea un problema molto più insidioso nascosto sotto la superficie: la trappola dell’ambito globale. Anche quando si lavora con architetture basate su componenti, i fotogrammi chiave CSS sono sempre definiti nell'ambito globale. Ciò significa che tutti i fotogrammi chiave si applicano a tutti i componenti. Sempre. Sì, la tua animazione non utilizza necessariamente i fotogrammi chiave che hai definito nel tuo componente. Utilizza gli ultimi fotogrammi chiave che corrispondono esattamente allo stesso nome caricati nell'ambito globale. Finché tutti i fotogrammi chiave sono identici, questo potrebbe sembrare un problema minore. Ma nel momento in cui desideri personalizzare un’animazione per un caso d’uso specifico, sei nei guai o, peggio, sarai tu a causarli. O la tua animazione non funzionerà perché un altro componente è stato caricato dopo il tuo, sovrascrivendo i tuoi fotogrammi chiave, oppure il tuo componente si carica per ultimo e modifica accidentalmente il comportamento dell'animazione per ogni altro componente utilizzando il nome di quel fotogramma chiave, e potresti anche non rendertene conto. Ecco un semplice esempio che dimostra il problema: .componente-uno { /* stili dei componenti */ animazione: impulso 1s easy-in-out alternato infinito; }
/* questa definizione di @keyframes non funzionerà */ @impulso fotogrammi chiave { da { scala: 1; } a { scala: 1.1; } }
/* più avanti nel codice... */
.componente-due { /* stili dei componenti */ animazione: impulso 1s easy-in-out infinito; }
/* questi fotogrammi chiave verranno applicati a entrambi i componenti */ @impulso fotogrammi chiave { 0%, 20%, 100% { scala: 1; } 10%, 40% { scala: 1,2; } }
Entrambi i componenti utilizzano lo stesso nome di animazione, ma la seconda definizione @keyframes sovrascrive la prima. Ora sia il componente uno che il componente due utilizzeranno i secondi fotogrammi chiave, indipendentemente da quale componente ha definito quali fotogrammi chiave. Guarda i token Pen Keyframes - Demo 1 [biforcato] di Amit Sheen. La parte peggiore? Questo spesso funziona perfettamente nello sviluppo locale ma si interrompe misteriosamente nella produzione quando i processi di compilazione modificano l'ordine di caricamento dei fogli di stile. Alla fine ti ritroverai con animazioni che si comportano diversamente a seconda di quali componenti vengono caricati e in quale sequenza. La soluzione: fotogrammi chiave unificati La risposta a questo caos è sorprendentemente semplice: fotogrammi chiave dinamici predefiniti archiviati in un foglio di stile condiviso. Invece di lasciare che ogni componente definisca le proprie animazioni, creiamo fotogrammi chiave centralizzati che sono ben documentati e facili da usareutilizzo, manutenibilità e su misura per le esigenze specifiche del vostro progetto. Pensatelo come token di fotogrammi chiave. Proprio come utilizziamo i token per i colori e la spaziatura, e molti di noi già utilizzano i token per le proprietà dell'animazione, come la durata e le funzioni di andamento, perché non utilizzare i token anche per i fotogrammi chiave? Questo approccio può integrarsi naturalmente con qualsiasi flusso di lavoro di token di progettazione corrente che stai utilizzando, risolvendo sia il piccolo problema (duplicazione del codice) che il problema più grande (conflitti di ambito globale) in una volta sola. L'idea è semplice: creare un'unica fonte di verità per tutte le nostre animazioni comuni. Questo foglio di stile condiviso contiene fotogrammi chiave realizzati con cura che coprono i modelli di animazione effettivamente utilizzati dal nostro progetto. Non è più necessario indovinare se esiste già un'animazione di dissolvenza da qualche parte nella nostra base di codice. Non sarà più necessario sovrascrivere accidentalmente le animazioni di altri componenti. Ma ecco la chiave: queste non sono solo animazioni statiche copia-incolla. Sono progettati per essere dinamici e personalizzabili tramite proprietà personalizzate CSS, permettendoci di mantenere la coerenza pur avendo la flessibilità di adattare le animazioni a casi d'uso specifici, come se avessi bisogno di un'animazione "a impulsi" leggermente più grande in un unico posto. Costruire il primo token keyframe Uno dei primi frutti a portata di mano che dovremmo affrontare è l'animazione "dissolvenza in apertura". In uno dei miei progetti recenti, ho trovato più di una dozzina di definizioni di dissolvenza in apertura separate e sì, tutte animavano semplicemente l'opacità da 0 a 1. Quindi, creiamo un nuovo foglio di stile, chiamiamolo kf-tokens.css, importiamolo nel nostro progetto e inseriamo i nostri fotogrammi chiave con i commenti appropriati al suo interno. /* keyframes-tokens.css */
/* * Fade In: animazione di ingresso in dissolvenza * Utilizzo: animazione: kf-fade-in 0.3s fade-out; */ @keyframes kf-fade-in { da { opacità: 0; } a { opacità: 1; } }
Questa singola dichiarazione @keyframes sostituisce tutte quelle animazioni in dissolvenza sparse nel nostro codice base. Pulito, semplice e applicabile a livello globale. E ora che abbiamo definito questo token, possiamo usarlo da qualsiasi componente del nostro progetto: .modale { animazione: kf-fade-in 0.3s fade-out; }
.descrizione comando { animazione: kf-fade-in 0.2s easy-in-out; }
.notifica { animazione: kf-fade-in 0.5s fade-out; }
Guarda i token Pen Keyframes - Demo 2 [biforcato] di Amit Sheen. Nota: utilizziamo un prefisso kf- in tutti i nomi dei nostri @keyframes. Questo prefisso funge da spazio dei nomi che impedisce conflitti di denominazione con le animazioni esistenti nel progetto e rende immediatamente chiaro che questi fotogrammi chiave provengono dal nostro file token dei fotogrammi chiave. Realizzazione di una diapositiva dinamica I fotogrammi chiave con dissolvenza in apertura funzionano alla grande perché sono semplici e c'è poco spazio per rovinare le cose. In altre animazioni, tuttavia, dobbiamo essere molto più dinamici e qui possiamo sfruttare l'enorme potenza delle proprietà personalizzate CSS. È qui che i token dei fotogrammi chiave brillano davvero rispetto alle animazioni statiche sparse. Prendiamo uno scenario comune: le animazioni “slide-in”. Ma entrare da dove? 100px da destra? 50% da sinistra? Dovrebbe entrare dalla parte superiore dello schermo? O forse fluttuare dal basso? Tante possibilità, ma invece di creare fotogrammi chiave separati per ogni direzione e ogni variazione, possiamo creare un token flessibile che si adatti a tutti gli scenari: /* * Slide In: animazione diapositiva direzionale * Usa --kf-slide-from per controllare la direzione * Predefinito: scorre da sinistra (-100%) * Utilizzo: * animazione: kf-slide-in 0.3s easy-out; * --kf-slide-from: -100px 0; // scorri da sinistra * --kf-slide-from: 100px 0; // scorri da destra * --kf-slide-from: 0 -50px; // scorri dall'alto */
@keyframes kf-slide-in { da { traduci: var(--kf-slide-from, -100% 0); } a { tradurre: 0 0; } }
Ora possiamo utilizzare questo singolo token @keyframes per qualsiasi direzione della diapositiva semplicemente modificando la proprietà personalizzata --kf-slide-from: .barra laterale { animazione: kf-slide-in 0.3s easy-out; /* Utilizza il valore predefinito: diapositive da sinistra */ }
.notifica { animazione: kf-slide-in 0.4s easy-out; --kf-slide-da: 0 -50px; /* scorri dall'alto */ }
.modale { animazione: kf-fade-in 0,5 s, kf-slide-in 0,5 s cubico-bezier(0,34, 1,56, 0,64, 1); --kf-slide-da: 50px 50px; /* scorri dal basso a destra */ }
Questo approccio ci offre un'incredibile flessibilità pur mantenendo la coerenza. Una dichiarazione di fotogrammi chiave, infinite possibilità. Guarda i token Pen Keyframes - Demo 3 [biforcato] di Amit Sheen. E se vogliamo rendere le nostre animazioni ancora più flessibili, permettendo anche effetti “slide-out”, possiamoaggiungi semplicemente una proprietà personalizzata --kf-slide-to, simile a quella che vedremo nella prossima sezione. Fotogrammi chiave di zoom bidirezionale Un'altra animazione comune che viene duplicata nei progetti sono gli effetti "zoom". Che si tratti di un leggero ingrandimento per i messaggi di avviso popup, di un drammatico ingrandimento per le modali o di un delicato effetto di riduzione per i titoli, le animazioni di zoom sono ovunque. Invece di creare fotogrammi chiave separati per ciascun valore di scala, creiamo un set flessibile di fotogrammi chiave kf-zoom:
/* * Zoom: animazione in scala * Usa --kf-zoom-from e --kf-zoom-to per controllare i valori di scala * Impostazione predefinita: zoom dall'80% al 100% (da 0,8 a 1) * Utilizzo: * animazione: kf-zoom 0,2s facilità di uscita; * --kf-zoom-da: 0,5; --kf-zoom-to: 1; // zooma dal 50% al 100% * --kf-zoom-from: 1; --kf-zoom-to: 0; // zoom dal 100% allo 0% * --kf-zoom-from: 1; --kf-zoom-to: 1.1; // zoom dal 100% al 110% */
@keyframe kf-zoom { da { scala: var(--kf-zoom-from, 0.8); } a { scala: var(--kf-zoom-to, 1); } }
Con una definizione, possiamo ottenere qualsiasi variazione di zoom di cui abbiamo bisogno: .pane tostato { animazione: kf-inserimento 0,2 s, kf-zoom 0,4 s allentamento; --kf-slide-da: 0 100%; /* scorri dall'alto */ /* Utilizza lo zoom predefinito: scala dall'80% al 100% */ }
.modale { animazione: kf-zoom 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); --kf-zoom-da: 0; /* zoom drammatico dallo 0% al 100% */ }
.intestazione { animazione: kf-dissolvenza in apertura 2s, kf-zoom 2s facilitato; --kf-zoom-da: 1.2; --kf-zoom-to: 0,8; /* ridimensiona leggermente */ }
Il valore predefinito di 0,8 (80%) funziona perfettamente per la maggior parte degli elementi dell'interfaccia utente, come messaggi di avviso popup e schede, pur essendo facile da personalizzare per casi speciali. Guarda i token Pen Keyframes - Demo 4 [biforcuto] di Amit Sheen. Potresti aver notato qualcosa di interessante negli esempi recenti: abbiamo combinato le animazioni. Uno dei principali vantaggi di lavorare con i token @keyframes è che sono progettati per integrarsi perfettamente tra loro. Questa composizione fluida è intenzionale, non casuale. Discuteremo la composizione delle animazioni in modo più dettagliato in seguito, compresi i punti in cui possono diventare problematiche, ma la maggior parte delle combinazioni sono semplici e facili da implementare. Nota: mentre scrivevo questo articolo, e forse proprio per questo motivo, mi sono ritrovato a ripensare l'intera idea delle animazioni di ingresso. Con tutti i recenti progressi nei CSS, ne abbiamo ancora bisogno? Fortunatamente, Adam Argyle ha esplorato le stesse domande e le ha espresse brillantemente nel suo blog. Ciò non contraddice quanto scritto qui, ma presenta un approccio che vale la pena considerare, soprattutto se i tuoi progetti fanno molto affidamento sulle animazioni di ingresso. Animazioni continue Mentre le animazioni di ingresso, come "dissolvenza", "scorrimento" e "zoom", si verificano una volta e poi si interrompono, le animazioni continue si ripetono all'infinito per attirare l'attenzione o indicare un'attività in corso. Le due animazioni continue più comuni che incontro sono "spin" (per gli indicatori di caricamento) e "pulse" (per evidenziare elementi importanti). Queste animazioni presentano sfide uniche quando si tratta di creare token di fotogrammi chiave. A differenza delle animazioni di ingresso che in genere passano da uno stato all'altro, le animazioni continue devono essere altamente personalizzabili nei loro modelli di comportamento. Lo Spin Doctor Ogni progetto sembra utilizzare più animazioni di rotazione. Alcuni girano in senso orario, altri in senso antiorario. Alcuni eseguono una singola rotazione di 360 gradi, altri eseguono più giri per un effetto più rapido. Invece di creare fotogrammi chiave separati per ogni variazione, creiamo una rotazione flessibile che gestisca tutti gli scenari:
/* * Spin: animazione di rotazione * Usa --kf-spin-from e --kf-spin-to per controllare l'intervallo di rotazione * Usa --kf-spin-turns per controllare la quantità di rotazione * Impostazione predefinita: ruota da 0° a 360° (1 rotazione completa) * Utilizzo: * animazione: kf-spin 1s lineare infinito; * --kf-spin-giri: 2; // 2 rotazioni complete * --kf-spin-from: 0deg; --kf-spin-to: 180 gradi; // mezza rotazione * --kf-spin-from: 0deg; --kf-spin-to: -360 gradi; // in senso antiorario */
@keyframes kf-spin { da { ruotare: var(--kf-spin-from, 0deg); } a { ruota: calc(var(--kf-spin-from, 0deg) + var(--kf-spin-to, 360deg) * var(--kf-spin-turns, 1)); } }
Ora possiamo creare qualsiasi variazione di spin che ci piace:
.spinner di caricamento { animazione: kf-spin 1s lineare infinito; /* Usa l'impostazione predefinita: ruota da 0° a 360° */ }
.caricatore veloce { animazione: kf-spin 1.2s easy-in-out alternativo infinito; --kf-spin-giri: 3; /* 3 rotazioni complete per ciascuna direzione per ciclo*/ }
.passo inverso { animazione: kf-spin 1.5s passi(8) infinito; --kf-spin-to: -360 gradi; /* in senso antiorario */ }
.sottile oscillazione { animazione: kf-spin 2s easy-in-out alternativo infinito; --kf-spin-da: -16 gradi; --kf-spin-to: 32 gradi; /* oscillazione di 36 gradi: tra -18 gradi e +18 gradi */ }
Guarda i token Pen Keyframes - Demo 5 [biforcato] di Amit Sheen. La bellezza di questo approccio è che gli stessi fotogrammi chiave funzionano per caricare filatori, icone rotanti, effetti di oscillazione e persino complesse animazioni multigiro. Il paradosso del polso Le animazioni a impulsi sono più complicate perché possono "impulsare" diverse proprietà. Alcuni pulsano la scala, altri pulsano l'opacità e alcuni pulsano le proprietà del colore come luminosità o saturazione. Invece di creare fotogrammi chiave separati per ciascuna proprietà, possiamo creare fotogrammi chiave che funzionino con qualsiasi proprietà CSS. Ecco un esempio di un fotogramma chiave a impulsi con opzioni di scala e opacità:
/* * Pulse: animazione pulsante * Utilizzare --kf-pulse-scale-from e --kf-pulse-scale-to per controllare l'intervallo della scala * Usa --kf-pulse-opacity-from e --kf-pulse-opacity-to per controllare l'intervallo di opacità * Impostazione predefinita: nessun impulso (tutti i valori 1) * Utilizzo: * animazione: kf-pulse 2s easy-in-out alternativo infinito; * --kf-pulse-scale-from: 0,95; --kf-pulse-scale-to: 1,05; // impulso in scala * --kf-pulse-opacity-from: 0,7; --kf-pulse-opacity-to: 1; // impulso di opacità */
@keyframes kf-pulse { da { scala: var(--kf-pulse-scale-from, 1); opacità: var(--kf-pulse-opacity-from, 1); } a { scala: var(--kf-pulse-scale-to, 1); opacità: var(--kf-pulse-opacity-to, 1); } }
Questo crea un impulso flessibile che può animare più proprietà: .invito all'azione { animazione: kf-pulse 0,6 s infinito alternato; --kf-pulse-opacity-from: 0,5; /* impulso di opacità */ }
.punto-notifica { animazione: kf-pulse 0.6s easy-in-out alternato infinito; --kf-pulse-scale-from: 0,9; --kf-pulse-scale-to: 1.1; /* impulso di scala */ }
.testo in evidenza { animazione: kf-pulse 1.5s easy-out infinito; --kf-scala-impulso-da: 0,8; --kf-pulse-opacity-from: 0,2; /* impulso di scala e opacità */ }
Guarda i token Pen Keyframes - Demo 6 [biforcato] di Amit Sheen. Questo singolo fotogramma chiave kf-pulse è in grado di gestire qualsiasi cosa, da sottili attiri di attenzione a punti salienti drammatici, il tutto pur essendo facile da personalizzare. Easing avanzato Uno degli aspetti positivi dell'utilizzo dei token keyframe è la facilità con cui è possibile espandere la nostra libreria di animazioni e fornire effetti che la maggior parte degli sviluppatori non si preoccuperebbe di scrivere da zero, come elastico o rimbalzo. Ecco un esempio di un semplice token di fotogrammi chiave "rimbalzo" che utilizza una proprietà personalizzata --kf-bounce-from per controllare l'altezza del salto. /* * Bounce: animazione dell'ingresso che rimbalza * Usa --kf-bounce-from per controllare l'altezza del salto * Predefinito: salta da 100vh (fuori schermo) * Utilizzo: * animazione: kf-bounce 3s easy-in; * --kf-bounce-from: 200px; // salta da un'altezza di 200px */
@keyframes kf-rimbalzo { 0% { traduci: 0 calc(var(--kf-bounce-from, 100vh) * -1); }
34% { traduci: 0 calc(var(--kf-bounce-from, 100vh) * -0.4); }
55% { traduci: 0 calc(var(--kf-bounce-from, 100vh) * -0.2); }
72% { traduci: 0 calc(var(--kf-bounce-from, 100vh) * -0.1); }
85% { traduci: 0 calc(var(--kf-bounce-from, 100vh) * -0.05); }
94% { traduci: 0 calc(var(--kf-bounce-from, 100vh) * -0.025); }
99% { traduci: 0 calc(var(--kf-bounce-from, 100vh) * -0.0125); }
22%, 45%, 64%, 79%, 90%, 97%, 100% { tradurre: 0 0; funzione di temporizzazione dell'animazione: facilità; } }
Animazioni come "elastica" sono un po' più complicate a causa dei calcoli all'interno dei fotogrammi chiave. Dobbiamo definire --kf-elastic-from-X e --kf-elastic-from-Y separatamente (entrambi sono opzionali) e insieme ci permettono di creare un ingresso elastico da qualsiasi punto dello schermo.
/* * Elastic In: animazione di ingresso elastico * Utilizza --kf-elastic-from-X e --kf-elastic-from-Y per controllare la posizione iniziale * Predefinito: entra dall'alto al centro (0, -100vh) * Utilizzo: * animazione: kf-elastic-in 2s easy-in-out entrambi; * --kf-elastic-from-X: -50px; * --kf-elastic-from-Y: -200px; // entra da (-50px, -200px) */
@keyframes kf-elastic-in { 0% { tradurre: calc(var(--kf-elastic-from-X, -50vw) * 1) calc(var(--kf-elastic-from-Y, 0px) * 1); }
16% { tradurre: calc(var(--kf-elastic-from-X, -50vw) * -0.3227) calc(var(--kf-elastic-from-Y, 0px) * -0.3227); }
28% { tradurre: calc(var(--kf-elastic-from-X, -50vw) * 0.1312)calc(var(--kf-elastic-from-Y, 0px) * 0.1312); }
44% { tradurre: calc(var(--kf-elastic-from-X, -50vw) * -0.0463) calc(var(--kf-elastic-from-Y, 0px) * -0.0463); }
59% { tradurre: calc(var(--kf-elastic-from-X, -50vw) * 0.0164) calc(var(--kf-elastic-from-Y, 0px) * 0.0164); }
73% { tradurre: calc(var(--kf-elastic-from-X, -50vw) * -0.0058) calc(var(--kf-elastic-from-Y, 0px) * -0.0058); }
88% { tradurre: calc(var(--kf-elastic-from-X, -50vw) * 0.0020) calc(var(--kf-elastic-from-Y, 0px) * 0.0020); }
100% { tradurre: 0 0; } }
Questo approccio semplifica il riutilizzo e la personalizzazione dei fotogrammi chiave avanzati nel nostro progetto, semplicemente modificando una singola proprietà personalizzata.
.rimbalza e zoom { animazione: kf-bounce 3s facilitato, kf-zoom 3s lineare; --kf-zoom-da: 0; }
.rimbalza e scivola { composizione-animazione: aggiungi; /* Entrambe le animazioni utilizzano la traduzione */ animazione: kf-bounce 3s facilitato, kf-slide-in 3s easy-out; --kf-slide-da: -200px; }
.elastico { animazione: kf-elastic-in 2s easy-in-out entrambi; }
Guarda i token Pen Keyframes - Demo 7 [biforcato] di Amit Sheen. Fino a questo punto abbiamo visto come consolidare i fotogrammi chiave in modo intelligente ed efficiente. Naturalmente, potresti voler modificare le cose per adattarle meglio alle esigenze del tuo progetto, ma abbiamo trattato esempi di diverse animazioni comuni e casi d'uso quotidiano. E con questi token di fotogrammi chiave in atto, ora disponiamo di potenti elementi costitutivi per creare animazioni coerenti e mantenibili nell'intero progetto. Niente più fotogrammi chiave duplicati, niente più conflitti di ambito globale. Solo un modo pulito e conveniente per gestire tutte le nostre esigenze di animazione. Ma la vera domanda è: come possiamo mettere insieme questi elementi costitutivi? Mettere tutto insieme Abbiamo visto che combinare i token dei fotogrammi chiave di base è semplice. Non abbiamo bisogno di nulla di speciale se non di definire la prima animazione, definire la seconda, impostare le variabili secondo necessità e il gioco è fatto. /* Dissolvenza in apertura + diapositiva in apertura */ .pane tostato { animazione: kf-fade-in 0,4 s, kf-slide-in 0,4 s cubico-bezier(0,34, 1,56, 0,64, 1); --kf-slide-da: 0 40px; }
/* Zoom avanti + dissolvenza in apertura */ .modale { animazione: kf-fade-in 0,3 s, kf-zoom 0,3 s cubico-bezier(0,34, 1,56, 0,64, 1); --kf-zoom-da: 0,7; --kf-zoom-to: 1; }
/* Inserisci + impulso */ .notifica { animazione: kf-inserimento 0,5 s, kf-pulse 1.2s easy-in-out alternato infinito; --kf-slide-from: -100px 0; --kf-scala-impulso-da: 0,95; --kf-pulse-scale-to: 1,05; }
Queste combinazioni funzionano magnificamente perché ogni animazione prende di mira una proprietà diversa: opacità, trasformazione (traduzione/scala), ecc. Ma a volte ci sono conflitti e dobbiamo sapere perché e come gestirli. Quando due animazioni tentano di animare la stessa proprietà, ad esempio entrambe le dimensioni dell'animazione o entrambe l'opacità dell'animazione, il risultato non sarà quello previsto. Per impostazione predefinita, a quella proprietà viene effettivamente applicata solo una delle animazioni, ovvero l'ultima nell'elenco delle animazioni. Questa è una limitazione del modo in cui i CSS gestiscono più animazioni sulla stessa proprietà. Ad esempio, questo non funzionerà come previsto perché verrà applicata solo l'animazione kf-pulse. .combo-cattivo { animazione: kf-zoom 0,5 s in avanti, kf-pulse 1.2s infinito alternato; --kf-zoom-da: 0,5; --kf-zoom-to: 1.2; --kf-scala-impulso-da: 0,8; --kf-pulse-scale-to: 1.1; }
Aggiunta di animazione Il modo più semplice e diretto per gestire più animazioni che influiscono sulla stessa proprietà è utilizzare la proprietà Animation-Composition. Nell'ultimo esempio sopra, l'animazione kf-pulse sostituisce l'animazione kf-zoom, quindi non vedremo lo zoom iniziale e non otterremo la scala prevista di 1,2. Impostando la composizione dell'animazione da aggiungere, diciamo al browser di combinare entrambe le animazioni. Questo ci dà il risultato che desideriamo. .componente-due { composizione-animazione: aggiungi; }
Guarda i token Pen Keyframes - Demo 8 [biforcato] di Amit Sheen. Questo approccio funziona bene nella maggior parte dei casi in cui vogliamo combinare gli effetti sulla stessa proprietà. È utile anche quando dobbiamo combinare animazioni con valori di proprietà statiche. Ad esempio, se abbiamo un elemento che utilizza la proprietà Translate per posizionarlo esattamente dove vogliamo, e poi vogliamo animarlo con i fotogrammi chiave kf-slide-in, otteniamo un brutto salto visibile senza composizione dell'animazione. Guarda i token Pen Keyframes - Demo 9 [biforcato] di Amit Sheen. Con la composizione dell'animazione impostata per l'aggiunta, l'animazione viene combinata senza problemi con quella esistentetrasformarsi, quindi l'elemento rimane al suo posto e si anima come previsto. Sfalsamento dell'animazione Un altro modo per gestire più animazioni è "scaglionarle", ovvero avviare la seconda animazione leggermente dopo il termine della prima. Non è una soluzione che funziona per tutti i casi, ma è utile quando abbiamo un'animazione di ingresso seguita da un'animazione continua. /* dissolvenza in apertura + impulso di opacità */ .notifica { animazione: kf-fade-in 2s facilità-out, kf-pulse 0,5s 2s easy-in-out alternato infinito; --kf-pulse-opacity-to: 0,5; }
Guarda i token Pen Keyframes - Demo 10 [biforcato] di Amit Sheen. L'ordine è importante Gran parte delle animazioni con cui lavoriamo utilizzano la proprietà di trasformazione. Nella maggior parte dei casi, questo è semplicemente più conveniente. Ha anche un vantaggio in termini di prestazioni poiché le animazioni di trasformazione possono essere accelerate dalla GPU. Ma se utilizziamo le trasformazioni, dobbiamo accettare che l'ordine in cui eseguiamo le trasformazioni è importante. Molto. Finora nei nostri fotogrammi chiave abbiamo utilizzato trasformazioni individuali. Secondo le specifiche, questi vengono sempre applicati in un ordine fisso: prima l'elemento viene traslato, quindi ruotato, quindi ridimensionato. Questo ha senso ed è ciò che la maggior parte di noi si aspetta. Tuttavia, se utilizziamo la proprietà di trasformazione, l'ordine in cui sono scritte le funzioni è l'ordine in cui vengono applicate. In questo caso, se spostiamo qualcosa di 100 pixel sull'asse X e poi lo ruotiamo di 45 gradi, non è la stessa cosa che ruotarlo prima di 45 gradi e poi spostarlo di 100 pixel. /* Quadrato rosa: prima trasla, poi ruota */ .esempio-uno { trasformazione: traduciX(100px) ruota(45 gradi); }
/* Quadrato verde: prima ruota, poi trasla */ .esempio-due { trasformazione: ruota (45 gradi) traduciX (100px); }
Guarda i token Pen Keyframes - Demo 11 [biforcato] di Amit Sheen. Ma secondo l’ordine di trasformazione, tutte le trasformazioni individuali – tutto ciò che abbiamo utilizzato per i token dei fotogrammi chiave – avviene prima delle funzioni di trasformazione. Ciò significa che tutto ciò che imposti nella proprietà di trasformazione avverrà dopo le animazioni. Ma se imposti, ad esempio, la traduzione insieme ai fotogrammi chiave kf-spin, la traduzione avverrà prima dell'animazione. Ancora confuso?! Ciò porta a situazioni in cui i valori statici possono causare risultati diversi per la stessa animazione, come nel caso seguente:
/* Animazione comune per entrambi gli spinner */ .spinner { animazione: kf-spin 1s lineare infinito; }
/* Spinner rosa: trasla prima della rotazione (trasformazione individuale) */ .spinner-rosa { tradurre: 100% 50%; }
/* Spinner verde: ruota e poi trasla (ordine delle funzioni) */ .spinner-verde { trasformare: tradurre(100%, 50%); }
Guarda i token Pen Keyframes - Demo 12 [biforcato] di Amit Sheen. Puoi vedere che il primo spinner (rosa) riceve una traslazione che avviene prima della rotazione di kf-spin, quindi prima si sposta al suo posto e poi gira. Il secondo spinner (verde) ottiene una funzione Translate() che avviene dopo la trasformazione individuale, quindi l'elemento prima gira, poi si sposta rispetto al suo angolo attuale e otteniamo quell'effetto di orbita ampia. No, questo non è un bug. È solo una di quelle cose che dobbiamo sapere sui CSS e tenere a mente quando lavoriamo con più animazioni o trasformazioni multiple. Se necessario, puoi anche creare un set aggiuntivo di fotogrammi chiave kf-spin-alt che ruotano gli elementi utilizzando la funzione rotate(). Movimento ridotto E mentre parliamo di fotogrammi chiave alternativi, non possiamo ignorare l’opzione “nessuna animazione”. Uno dei maggiori vantaggi dell'utilizzo dei token keyframe è che l'accessibilità può essere integrata ed è in realtà abbastanza semplice da fare. Progettando i nostri fotogrammi chiave tenendo presente l'accessibilità, possiamo garantire che gli utenti che preferiscono il movimento ridotto ottengano un'esperienza più fluida e con meno distrazioni, senza lavoro aggiuntivo o duplicazione del codice. Il significato esatto di "Movimento ridotto" può cambiare leggermente da un'animazione all'altra e da un progetto all'altro, ma ecco alcuni punti importanti da tenere a mente: Disattivazione dei fotogrammi chiave Mentre alcune animazioni possono essere ammorbidite o rallentate, ce ne sono altre che dovrebbero scomparire completamente quando viene richiesto il movimento ridotto. Le animazioni a impulsi sono un buon esempio. Per assicurarci che queste animazioni non vengano eseguite in modalità di movimento ridotto, possiamo semplicemente racchiuderle nella query multimediale appropriata.
@media (preferisce il movimento ridotto: nessuna preferenza) { @keyfrmaes kf-pulse { da { scala: var(--kf-pulse-scale-from, 1); opacità: var(--kf-pulse-opacity-from, 1); } a { scala: var(--kf-pulse-scale-to, 1); opacità:var(--kf-pulse-opacity-to, 1); } } }
Ciò garantisce che gli utenti che hanno impostato Prefers-Reduced-Motion su Reduce non vedranno l'animazione e otterranno un'esperienza che corrisponde alle loro preferenze. Ingresso istantaneo Ci sono alcuni fotogrammi chiave che non possiamo semplicemente rimuovere, come le animazioni di ingresso. Il valore deve cambiare, deve animarsi; in caso contrario, l'elemento non avrà i valori corretti. Ma nel movimento ridotto, questa transizione dal valore iniziale dovrebbe essere istantanea. Per raggiungere questo obiettivo, definiremo un set aggiuntivo di fotogrammi chiave in cui il valore passa immediatamente allo stato finale. Questi diventano i nostri fotogrammi chiave predefiniti. Quindi, aggiungeremo i fotogrammi chiave regolari all'interno di una query multimediale per prefers-reduced-motion impostata su nessuna preferenza, proprio come nell'esempio precedente. /* entra immediatamente per ridurre il movimento */ @keyframe kf-zoom { da, a { scala: var(--kf-zoom-to, 1); } }
@media (preferisce il movimento ridotto: nessuna preferenza) { /* Fotogrammi chiave di zoom originali */ @keyframe kf-zoom { da { scala: var(--kf-zoom-from, 0.8); } a { scala: var(--kf-zoom-to, 1); } } }
In questo modo, gli utenti che preferiscono il movimento ridotto vedranno l'elemento apparire istantaneamente nel suo stato finale, mentre tutti gli altri avranno la transizione animata. L'approccio morbido Ci sono casi in cui vogliamo mantenere un po' di movimento, ma molto più morbido e calmo rispetto all'animazione originale. Ad esempio, possiamo sostituire un ingresso rimbalzato con una delicata dissolvenza in apertura.
@keyframes kf-rimbalzo { /* Soft fade-in per ridurre il movimento */ }
@media (preferisce il movimento ridotto: nessuna preferenza) { @keyframes kf-rimbalzo { /* Fotogrammi chiave di rimbalzo originali */ } }
Ora, gli utenti con il movimento ridotto abilitato ottengono ancora un senso dell'apparenza, ma senza il movimento intenso di un rimbalzo o di un'animazione elastica. Una volta predisposti gli elementi costitutivi, la domanda successiva è come renderli parte del flusso di lavoro effettivo. Scrivere fotogrammi chiave flessibili è una cosa, ma renderli affidabili in un progetto di grandi dimensioni richiede alcune strategie che ho dovuto imparare nel modo più duro. Strategie di implementazione e migliori pratiche Una volta che disponiamo di una solida libreria di token keyframe, la vera sfida è come inserirli nel lavoro quotidiano.
La tentazione è di inserire tutti i fotogrammi chiave in una volta e dichiarare il problema risolto, ma in pratica ho scoperto che i risultati migliori derivano da un'adozione graduale. Inizia con le animazioni più comuni, come dissolvenza o diapositiva. Si tratta di vittorie facili che mostrano un valore immediato senza richiedere grandi riscritture. La denominazione è un altro punto che merita attenzione. Un prefisso o uno spazio dei nomi coerente rende ovvio quali animazioni sono token e quali sono locali una tantum. Previene inoltre le collisioni accidentali e aiuta i nuovi membri del team a riconoscere a colpo d'occhio il sistema condiviso. La documentazione è importante quanto il codice stesso. Anche un breve commento sopra ogni token di fotogramma chiave può farti risparmiare ore di tentativi in seguito. Uno sviluppatore dovrebbe essere in grado di aprire il file dei token, cercare l'effetto di cui ha bisogno e copiare il modello di utilizzo direttamente nel proprio componente. La flessibilità è ciò che rende questo approccio degno dello sforzo. Esponendo proprietà personalizzate sensate, diamo ai team la possibilità di adattare l'animazione senza interrompere il sistema. Allo stesso tempo, cerca di non complicare eccessivamente. Fornisci le manopole che contano e mantieni il resto supponente. Infine, ricorda l’accessibilità. Non tutte le animazioni necessitano di un'alternativa a movimento ridotto, ma molte lo fanno. Integrare tempestivamente queste modifiche significa che non dovremo mai aggiornarle in un secondo momento e dimostra un livello di attenzione che i nostri utenti noteranno anche se non ne parlano mai.
Nella mia esperienza, trattare i token dei fotogrammi chiave come parte del nostro flusso di lavoro dei token di progettazione è ciò che li fa restare. Una volta posizionati, smettono di sembrare effetti speciali e diventano parte del linguaggio del design, un'estensione naturale del modo in cui il prodotto si muove e risponde. Concludendo Le animazioni possono essere una delle parti più gioiose della creazione di interfacce, ma senza struttura possono anche diventare una delle maggiori fonti di frustrazione. Trattando i fotogrammi chiave come token, prendi qualcosa che di solito è disordinato e difficile da gestire e lo trasformi in un sistema chiaro e prevedibile. Il vero valore non sta solo nel salvare poche righe di codice. È nella certezza che quando usi una dissolvenza, una diapositiva, uno zoom o una rotazione, sai esattamente come si comporterà nel progetto. È nella flessibilità che deriva dalle proprietà personalizzate senza il caos di infinite variazioni. Ed è nell'accessibilità incorporata nelle fondamenta piuttosto che aggiunta come taleun ripensamento. Ho visto queste idee funzionare in team diversi e basi di codice diverse e lo schema è sempre lo stesso. Una volta posizionati i token, i fotogrammi chiave smettono di essere una raccolta sparsa di trucchi e diventano parte del linguaggio di progettazione. Rendono il prodotto più intenzionale, più coerente e più vivo. Se prendi una cosa da questo articolo, lascia che sia questa: le animazioni meritano la stessa cura e struttura che già diamo ai colori, alla tipografia e alla spaziatura. Un piccolo investimento in token keyframe ripaga ogni volta che la tua interfaccia si sposta.