Quattro nuove funzionalità CSS per animazioni di ingresso e uscita fluide

Il movimento è una parte fondamentale di qualsiasi esperienza digitale e guida l'utente da un'interazione all'altra. Tuttavia, ci sono alcune lacune nelle animazioni fluide sulla piattaforma web. Queste includono la possibilità di animare facilmente le animazioni di ingresso e uscita e di animare facilmente da e verso il livello superiore per elementi ignorabili come finestre di dialogo e popover.

Per colmare queste lacune, Chrome 116 e 117 includono quattro nuove funzionalità della piattaforma web, che consentono animazioni e transizioni fluide per proprietà discrete.

Queste quattro nuove funzionalità includono:

  • La possibilità di animare display e content-visibility sulla sequenza temporale di un fotogramma chiave (da Chrome 116).
  • La proprietà transition-behavior con la parola chiave allow-discrete per consentire le transizioni di proprietà discrete come display (da Chrome 117).
  • La regola @starting-style per animare gli effetti di ingresso da display: none e nel livello superiore (da Chrome 117).
  • La proprietà overlay per controllare il comportamento del livello superiore durante un'animazione (da Chrome 117).

Visualizza animazioni nei fotogrammi chiave

In Chrome 116, puoi utilizzare display e content-visibility nelle regole per i fotogrammi chiave. Queste verranno scambiate nel momento in cui si trova il fotogramma chiave. Non sono necessari nuovi valori aggiuntivi a supporto:

.card {
  animation: fade-out 0.5s forwards;
}

@keyframes fade-out {
  100% {
    opacity: 0;
    display: none;
  }
}

L'esempio precedente anima l'opacità su 0 per una durata di 0,5 secondi e poi imposta la visualizzazione su nessuno. Inoltre, la parola chiave forwards garantisce che l'animazione rimanga allo stato finale, in modo che l'elemento a cui viene applicata rimanga display: none e opacity: 0.

Questo è un semplice esempio che riproduce ciò che puoi fare con una transizione (vedi la demo nella sezione dedicata alla transizione). Le transizioni, tuttavia, non sono in grado 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. Per prima cosa, la scheda ruoterà sull'asse Y, passerà attraverso una rotazione di tonalità, quindi al punto 80% della sequenza temporale, effettuerà la transizione dell'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, collegando un listener di eventi a un pulsante che attiva una classe per applicare l'animazione, in questo modo:

.spin-out {
   animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
 document.querySelector('.card').classList.add('spin-out');
})

L'esempio precedente ora ha uno stato finale display:none. In molti casi conviene andare oltre e rimuovere il nodo DOM con un timeout per consentire il completamento dell'animazione per prima.

Transizione di animazioni discrete

A differenza dell'animazione di proprietà discrete con i fotogrammi chiave, per eseguire la transizione di proprietà discrete devi utilizzare la modalità di transizione allow-discrete.

La proprietà transition-behavior

La modalità allow-discrete è ciò che rende possibili le transizioni discrete ed è 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;
}
Nota: questa demo sulle transizioni mostra una tecnica diversa rispetto alla prima demo di animazione, ma ha un aspetto simile.

La forma abbreviata transition imposta anche 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 stai animando 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 questo articolo ha trattato le animazioni di uscita. Per creare animazioni di voce 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. Questo è lo stato "prima dell'apertura" (da cui stai eseguendo 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 sono presenti uno stato di ingresso e uno di uscita per questi elementi dell'elenco DA FARE:

Animazione di 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 avviare l'animazione. Per una finestra di dialogo, lo stato di apertura è definito con l'attributo [open]. Per un popover, utilizza la pseudo classe :popover-open.

Un semplice esempio di finestra di dialogo potrebbe avere il seguente aspetto:

/*   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 uscita sono diversi. Inserisci un'animazione verso l'alto dalla parte inferiore dell'area visibile, esci dall'effetto nella parte superiore dell'area visibile. Inoltre, è scritto con CSS nidificato per una migliore incapsulamento visivo.

Quando anima un popover, utilizza la pseudo classe :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 eliminare popover o dialog dal livello superiore, aggiungi la proprietà overlay all'elenco delle transizioni. popover e dialog eseguono l'escape dei clip e delle trasformazioni predecessore e inseriscono i contenuti nel livello superiore. Se non esegui la transizione di overlay, l'elemento tornerà immediatamente a essere ritagliato, trasformato e coperto, e non vedrai la transizione.

[open] {
  transition: opacity 1s, display 1s allow-discrete;
}

Includi invece overlay nella transizione o nell'animazione per animare overlay insieme al resto degli elementi e assicurati che rimanga nel livello superiore durante l'animazione. L'operazione risulterà molto più fluida.

[open] {
  transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}

Inoltre, se hai più elementi aperti nello strato superiore, la sovrapposizione ti aiuta a controllare la transizione fluida dentro e fuori il livello superiore. Puoi vedere la differenza in questo semplice esempio. Se non applichi overlay al secondo popover al momento della transizione, questo uscirà dal strato superiore, passando dietro all'altro popover, prima di iniziare la transizione. L'effetto non è molto uniforme.

Una nota sulle transizioni delle viste

Se apporti modifiche al DOM, ad esempio aggiungi e rimuovi elementi dal DOM, un'altra ottima soluzione per creare animazioni fluide sono le transizioni di visualizzazione. Ecco due degli esempi precedenti creati utilizzando le transizioni di visualizzazione.

In questa prima demo, invece di configurare @starting-style e altre trasformazioni CSS, le transizioni della vista gestiranno la transizione. La transizione della visualizzazione è impostata in questo modo:

Innanzitutto, assegna a ogni carta un singolo view-transition-name in CSS.

.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 come questa operazione può essere utile è la demo di aggiunta/rimozione degli elementi dell'elenco. In questo caso, dovrai ricordarti di aggiungere un view-transition-name univoco per ogni carta creata.

Conclusione

Queste nuove funzionalità della piattaforma ci fanno un passo avanti per rendere fluide le animazioni di ingresso e uscita sulla piattaforma web. Per saperne di più, dai un'occhiata a questi link: