Il movimento è una parte fondamentale di qualsiasi esperienza digitale e guida l'utente da un'interazione all'altra. Ci sono però alcune lacune nelle animazioni fluide della piattaforma web. Queste includono la possibilità di animare facilmente le animazioni di entrata e uscita, nonché di animare in modo fluido da e verso il livello superiore per gli elementi ignorabili come finestre di dialogo e popover.
Per colmare queste lacune, Chrome 116 e Chrome 117 includono quattro nuove funzionalità delle piattaforme web, che consentono animazioni e transizioni fluide per proprietà discrete.
Queste quattro nuove funzionalità includono:
- La possibilità di animare
display
econtent-visibility
in una sequenza temporale di un fotogramma chiave (da Chrome 116). - La proprietà
transition-behavior
con la parola chiaveallow-discrete
per consentire le transizioni di proprietà discrete comedisplay
(da Chrome 117). - La regola
@starting-style
per animare gli effetti delle voci dadisplay: none
e nel livello superiore (Da Chrome 117). - La proprietà
overlay
per controllare il comportamento del livello superiore durante un'animazione (da Chrome 117). ## Mostrare animazioni nei fotogrammi chiave
A partire da Chrome 116, puoi utilizzare display
e content-visibility
nelle regole per i fotogrammi chiave. Questi verranno scambiati nel momento in cui si verifica il fotogramma chiave. Non sono richiesti nuovi valori aggiuntivi a supporto di ciò:
.card {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
L'esempio precedente imposta l'opacità su 0 nel periodo di 0,5 secondi, quindi imposta la visualizzazione su nessuno. Inoltre, la parola chiave forwards
assicura che l'animazione rimanga nello stato finale, in modo che l'elemento a cui viene applicata rimanga display: none
e opacity: 0
.
Questo è un semplice esempio che imita ciò che puoi fare con una transizione (vedi la demo nella sezione sulla transizione). Tuttavia, le transizioni non consentono di creare animazioni più complesse, come nell'esempio seguente:
.card {
animation: spin-and-delete 1s ease-in forwards;
}
@keyframes spin-and-delete {
0% {
transform: rotateY(0);
filter: hue-rotate(0);
}
80% {
transform: rotateY(360deg);
filter: hue-rotate(180deg);
opacity: 1;
}
100% {
opacity: 0;
display: none;
}
}
L'animazione spin-and-delete
è un'animazione di uscita. In primo luogo, la scheda ruoterà sull'asse y, si sposterà in una rotazione delle tonalità, quindi, nella sequenza temporale 80%
, passerà la sua opacità da 1 a 0. Infine, la carta passa da display: block
a display: none
.
Per queste animazioni di uscita, invece di applicarle direttamente a un elemento, puoi impostare un attivatore per le animazioni. Ad esempio, associando un listener di eventi a un pulsante che attiva una classe per applicare l'animazione, come nell'esempio seguente:
.spin-out {
animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
document.querySelector('.card').classList.add('spin-out');
})
Lo stato finale dell'esempio riportato sopra ora è display:none
. In molti casi è consigliabile spingersi oltre e rimuovere il nodo DOM con un timeout per consentire il primo completamento dell'animazione.
Transizione da animazioni discrete
A differenza dell'animazione delle proprietà discrete con i fotogrammi chiave, per trasferire le proprietà discrete devi utilizzare la modalità di transizione allow-discrete
.
La proprietà transition-behavior
Ciò che rende possibili le transizioni discrete è la modalità allow-discrete
, un valore della proprietà transition-behavior
. transition-behavior
accetta due valori: normal
e allow-discrete
.
.card {
transition: opacity 0.25s, display 0.25s;
transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}
.card.fade-out {
opacity: 0;
display: none;
}
Anche l'abbreviazione transition
imposta questo valore, quindi puoi omettere la proprietà e utilizzare invece la parola chiave allow-discrete
alla fine dell'abbreviazione transition
per ogni transizione.
.card {
transition: opacity 0.5s, display 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
Se vuoi animare più proprietà discrete, devi includere allow-discrete
dopo ogni proprietà che vuoi animare. Ad esempio:
.card {
transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
La regola @starting-style
per le animazioni delle voci
Finora in questo articolo sono state illustrate le animazioni di uscita. Per creare animazioni di entrata devi utilizzare la regola @starting-style
.
Utilizza @starting-style
per applicare uno stile che il browser può cercare prima che l'elemento sia aperto nella pagina. Si tratta dello stato "prima dell'apertura" (dal punto in cui viene eseguita l'animazione).
/* 0. BEFORE-OPEN STATE */
/* Starting point for the transition */
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
/* 1. IS-OPEN STATE */
/* The state at which the element is open + transition logic */
.item {
height: 3rem;
display: grid;
overflow: hidden;
transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}
/* 2. EXITING STATE */
/* While it is deleting, before DOM removal in JS, apply this
transformation for height, opacity, and a transform which
skews the element and moves it to the left before setting
it to display: none */
.is-deleting {
opacity: 0;
height: 0;
display: none;
transform: skewX(50deg) translateX(-25vw);
}
Ora hai sia uno stato di entrata che di uscita per questi elementi dell'elenco DA FARE:
Animazione degli elementi da e verso il livello superiore
Per animare gli elementi da e verso il livello superiore, specifica @starting-style
nello stato "aperto" per indicare al browser da dove eseguire l'animazione. Per una finestra di dialogo, lo stato aperto viene definito con l'attributo [open]
. Per un popover, utilizza la pseudoclasse :popover-open
.
Ecco un semplice esempio di una finestra di dialogo:
/* 0. BEFORE-OPEN STATE */
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
/* 1. IS-OPEN STATE */
dialog[open] {
translate: 0 0;
}
/* 2. EXIT STATE */
dialog {
transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
translate: 0 100vh;
}
Nel prossimo esempio, gli effetti di entrata e di uscita sono diversi. Inizia animando verso l'alto dalla parte inferiore dell'area visibile, quindi esci dall'effetto nella parte superiore dell'area visibile. Inoltre, è scritto con CSS nidificato per un maggiore incapsulamento visivo.
Quando crei un popover, utilizza la pseudoclasse :popover-open
anziché l'attributo open
usato in precedenza.
.settings-popover {
&:popover-open {
/* 0. BEFORE-OPEN STATE */
/* Initial state for what we're animating *in* from,
in this case: goes from lower (y + 20px) to center */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
/* 1. IS-OPEN STATE */
/* state when popover is open, BOTH:
what we're transitioning *in* to
and transitioning *out* from */
transform: translateY(0);
opacity: 1;
}
/* 2. EXIT STATE */
/* Initial state for what we're animating *out* to ,
in this case: goes from center to (y - 50px) higher */
transform: translateY(-50px);
opacity: 0;
/* Enumerate transitioning properties,
including display and allow-discrete mode */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
overlay
struttura
Infine, per far scomparire un elemento popover
o dialog
dal livello superiore, aggiungi la proprietà overlay
al tuo elenco di transizioni. popover
e dialog
eseguono l'escape dei clip dei predecessori e delle trasformazioni e inseriscono i contenuti nel livello superiore. Se non esegui la transizione di overlay
, il tuo elemento tornerà immediatamente a essere troncato, trasformato e coperto e non vedrai la transizione accadere.
[open] {
transition: opacity 1s, display 1s allow-discrete;
}
Includi overlay
nella transizione o nell'animazione per creare l'animazione di overlay
insieme al resto delle funzionalità e assicurarti che rimanga nel livello superiore durante l'animazione. Il risultato sarà molto più fluido.
[open] {
transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}
Inoltre, quando più elementi sono aperti nel livello superiore, l'overlay consente di controllare la transizione fluida da e verso il livello superiore. Puoi notare la differenza in questo semplice esempio. Se non applichi overlay
al secondo popover durante la transizione, verrà spostato prima dal livello superiore, saltando dietro l'altro popover, prima di iniziare la transizione. Questo non è un effetto molto uniforme.
Nota sulle transizioni delle visualizzazioni
Se stai apportando modifiche al DOM, ad esempio aggiungendo e rimuovendo elementi dal DOM, un'altra ottima soluzione per animazioni fluide è le transizioni di visualizzazione. Ecco due degli esempi precedenti creati utilizzando le transizioni delle viste.
In questa prima demo, invece di configurare @starting-style
e altre trasformazioni CSS, verranno gestite le transizioni delle viste. La transizione della visualizzazione avviene nel seguente modo:
Innanzitutto, in CSS, assegna un view-transition-name
a ogni scheda.
.card-1 {
view-transition-name: card-1;
}
.card-2 {
view-transition-name: card-2;
}
/* etc. */
Quindi, in JavaScript, aggrega la mutazione del DOM (in questo caso rimuovendo la scheda) in una transizione di visualizzazione.
deleteBtn.addEventListener('click', () => {
// Check for browser support
if (document.startViewTransition) {
document.startViewTransition(() => {
// DOM mutation
card.remove();
});
}
// Alternative if no browser support
else {
card.remove();
}
})
Ora il browser può gestire la dissolvenza in uscita e il morphing di ogni scheda nella nuova posizione.
Un altro esempio di questa funzionalità è la demo di aggiunta/rimozione di elementi dall'elenco. In questo caso, dovrai ricordarti di aggiungere un view-transition-name
univoco per ogni scheda creata.
Conclusione
Queste nuove funzionalità della piattaforma ci avvicinano a un'animazione fluida di accesso e uscita sulla piattaforma web. Per saperne di più, dai un'occhiata a questi link: