Inizia a utilizzare le animazioni basate sullo scorrimento in CSS

1. Prima di iniziare

Le animazioni basate sullo scorrimento ti consentono di controllare la riproduzione di un'animazione in base alla posizione di scorrimento di un contenitore di scorrimento. Ciò significa che, quando scorri verso l'alto o verso il basso, l'animazione esegue lo scrubbing in avanti o indietro. Inoltre, con le animazioni basate sullo scorrimento puoi controllare un'animazione in base alla posizione di un elemento all'interno del relativo contenitore di scorrimento. In questo modo puoi creare effetti interessanti, come un'immagine di sfondo con parallasse, barre di avanzamento di scorrimento e immagini che si rivelano non appena vengono visualizzate.

Le novità di Chrome 115 includono il supporto di un insieme di classi JavaScript e proprietà CSS che consentono di creare facilmente animazioni dichiarative basate sullo scorrimento. Queste nuove API funzionano in combinazione con le API delle animazioni web e delle animazioni CSS esistenti.

Questo codelab ti insegna come creare animazioni basate sullo scorrimento utilizzando CSS. Completando questo codelab, acquisirai familiarità con le molte nuove proprietà CSS introdotte da questa entusiasmante funzionalità, come scroll-timeline, view-timeline, animation-timeline e animation-range.

Obiettivi didattici

  • Come creare uno sfondo con parallasse con una sequenza temporale di scorrimento in CSS.
  • Come creare una barra di avanzamento con una sequenza temporale di scorrimento in CSS.
  • Come creare un effetto di rivelazione di un'immagine con una sequenza temporale di visualizzazione in CSS.
  • Come scegliere come target diversi tipi di intervalli di una sequenza temporale della visualizzazione in CSS.

Che cosa ti serve

Una delle seguenti combinazioni di dispositivi:

  • Una versione recente di Chrome (115 o versioni successive) su ChromeOS, macOS o Windows con le "Funzionalità sperimentali della piattaforma web" impostato su enabled.
  • Conoscenza di base del codice HTML
  • Conoscenza di base del linguaggio CSS, in particolare delle animazioni in CSS

2. Configurazione

Tutto ciò di cui hai bisogno per questo progetto è disponibile in un repository GitHub. Per iniziare, clona il codice e aprilo nel tuo ambiente di sviluppo preferito.

  1. Apri una nuova scheda del browser e vai a https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab.
  2. Clonare il repository.
  3. Apri il codice nel tuo IDE preferito.
  4. Esegui npm install per installare le dipendenze.
  5. Esegui npm start e visita http://localhost:3000/.
  6. In alternativa, se non hai installato npm, apri il file src/index.html in Chrome.

3. Scopri di più sulle sequenze temporali dell'animazione

Per impostazione predefinita, nella sequenza temporale dei documenti viene eseguita un'animazione collegata a un elemento. Ciò significa che, al caricamento della pagina, l'animazione scorre in avanti man mano che il tempo passa. Questa è la sequenza temporale predefinita dell'animazione e, fino a questo momento, era l'unica sequenza temporale dell'animazione a cui avevi accesso.

Con le animazioni basate sullo scorrimento, hai accesso a due nuovi tipi di sequenze temporali:

  • Sequenza temporale dell'avanzamento di scorrimento
  • Visualizza cronologia avanzamento

In CSS, queste sequenze temporali possono essere collegate a un'animazione utilizzando la proprietà animation-timeline. Dai un'occhiata al significato di queste nuove tempistiche e alle differenze tra loro.

Sequenza temporale dell'avanzamento di scorrimento

Una sequenza temporale dell'avanzamento di scorrimento è una sequenza temporale dell'animazione collegata all'avanzamento nella posizione di scorrimento di un contenitore di scorrimento, detta anche area di scorrimento o dispositivo di scorrimento, lungo un determinato asse. Converte una posizione in un intervallo di scorrimento in una percentuale di avanzamento lungo una sequenza temporale.

La posizione di scorrimento iniziale rappresenta l'avanzamento dello 0%, mentre la posizione di fine scorrimento rappresenta l'avanzamento del 100%. Nella visualizzazione seguente, tieni presente che l'avanzamento passa da 0% a 100% mentre scorri la barra di scorrimento.

Visualizza cronologia avanzamento

Questo tipo di sequenza temporale è collegata all'avanzamento relativo di un determinato elemento all'interno di un contenitore di scorrimento. Proprio come una sequenza temporale di avanzamento di scorrimento, viene monitorato l'offset di scorrimento di uno scorrimento. A differenza della sequenza temporale dell'avanzamento dello scorrimento, è la posizione relativa di un soggetto all'interno dello scorrimento che determina l'avanzamento. Questo è paragonabile a IntersectionObserver, che tiene traccia di quanto un elemento è visibile nello scorrimento. Se l'elemento non è visibile nello scorrimento, non si interseca. Se è visibile all'interno della barra di scorrimento, anche nella parte più piccola, si interseca.

La sequenza temporale dell'avanzamento della visualizzazione inizia dal momento in cui un soggetto inizia a intersecarsi con la barra di scorrimento e termina quando il soggetto smette di intersecarsi con la barra di scorrimento. Nella visualizzazione seguente, nota che l'avanzamento inizia il conteggio dallo 0% quando il soggetto entra nel contenitore di scorrimento e raggiunge il 100% nel momento in cui esce dal contenitore.

Per impostazione predefinita, un'animazione collegata alla sequenza temporale dell'avanzamento della visualizzazione viene associata all'intero intervallo. L'operazione inizia dal momento in cui il soggetto entra nell'area di scorrimento e termina quando il soggetto esce dall'area di scorrimento.

È anche possibile collegarlo a una parte specifica della sequenza temporale dell'avanzamento della visualizzazione specificando l'intervallo a cui deve essere associato. Ad esempio, questo può avvenire solo quando il soggetto sta entrando nella barra di scorrimento. Nella visualizzazione seguente, l'avanzamento inizia il conteggio dallo 0% quando il soggetto entra nel contenitore di scorrimento, ma raggiunge già il 100% dal momento in cui si interseca completamente.

I possibili intervalli di Spostamenti di Visualizza che puoi scegliere come target sono cover, contain, entry, exit, entry-crossing e exit-crossing. Questi intervalli sono spiegati più avanti in questo codelab, ma se non puoi aspettare, utilizza lo strumento disponibile all'indirizzo https://goo.gle/view-timeline-range-tool per vedere cosa rappresenta ogni intervallo.

4. Crea un effetto di sfondo con parallasse

Il primo effetto da aggiungere alla pagina è un effetto di sfondo con parallasse sull'immagine di sfondo principale. Mentre scorri la pagina verso il basso, l'immagine di sfondo dovrebbe muoversi, anche se a una velocità diversa. A questo scopo, fai affidamento sulla sequenza temporale dell'avanzamento di scorrimento.

A questo scopo, occorre seguire due passaggi:

  1. Crea un'animazione che sposti la posizione dell'immagine di sfondo.
  2. Collega l'animazione all'avanzamento di scorrimento del documento.

Crea l'animazione

  1. Per creare l'animazione, utilizza un insieme regolare di fotogrammi chiave. Al suo interno, sposta la posizione dello sfondo da 0% verticalmente a 100%:

src/styles.css

@keyframes move-background {
  from {
    background-position: 50% 0%;
  }
  to {
    background-position: 50% 100%;
  }
}
  1. Ora collega questi fotogrammi chiave all'elemento body:

src/styles.css

body {
  animation: 1s linear move-background;
}

Con questo codice, l'animazione move-background viene aggiunta all'elemento body. La sua proprietà animation-duration è impostata su un secondo e utilizza un easing linear.

Il modo più semplice per creare una sequenza temporale di avanzamento di scorrimento è utilizzare la funzione scroll(). Viene creata una cronologia dell'avanzamento di scorrimento anonima che puoi impostare come valore per la proprietà animation-timeline.

La funzione scroll() accetta un argomento <scroller> e un argomento <axis>.

I valori accettati per l'argomento <scroller> sono i seguenti:

  • nearest. Utilizza il container di scorrimento del predecessore più vicino (impostazione predefinita).
  • root. Utilizza l'area visibile del documento come contenitore di scorrimento.
  • self. Utilizza l'elemento stesso come contenitore di scorrimento.

I valori accettati per l'argomento <axis> sono i seguenti:

  • block. Utilizza la misura dell'avanzamento lungo l'asse del blocco del contenitore di scorrimento (impostazione predefinita).
  • inline. Utilizza la misura dell'avanzamento lungo l'asse in linea del contenitore di scorrimento.
  • y. Utilizza la misura dell'avanzamento lungo l'asse y del contenitore di scorrimento.
  • x. Utilizza la misura dell'avanzamento lungo l'asse X del contenitore di scorrimento.

Per collegare l'animazione allo scorrimento principale sull'asse del blocco, i valori da trasmettere a scroll() sono root e block. Complessivamente, il valore è scroll(root block).

  • Imposta scroll(root block) come valore per la proprietà animation-timeline nel corpo.
  • Inoltre, poiché un valore animation-duration espresso in secondi non ha senso, imposta la durata su auto. Se non specifichi un valore animation-duration, il valore predefinito sarà auto.

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(root block);
}

Poiché anche lo scorrimento principale è lo scorrimento principale più vicino per l'elemento body, puoi utilizzare anche il valore nearest:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(nearest block);
}

Poiché nearest e block sono i valori predefiniti, puoi anche scegliere di ometterli. In questo caso, il codice può essere semplificato come segue:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll();
}

Verifica le modifiche

Se tutto è andato bene, ora dovresti avere questo:

In caso contrario, controlla il ramo solution-step-1 del codice.

5. Creare una barra di avanzamento per la galleria immagini

Nella pagina è presente un carosello orizzontale che richiede una barra di avanzamento per indicare la foto che stai visualizzando.

Il markup per il carosello ha il seguente aspetto:

src/index.html

<div class="gallery">
  <div class="gallery__scrollcontainer" style="--num-images: 3;">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
  </div>
</div>

I fotogrammi chiave della barra di avanzamento sono già presenti e hanno il seguente aspetto:

src/styles.css

@keyframes adjust-progress {
  from {
    transform: scaleX(calc(1 / var(--num-images)));
  }
  to {
    transform: scaleX(1);
  }
}

Questa animazione deve essere allegata al file .Elemento gallery__progress con una cronologia dell'avanzamento di scorrimento. Come mostrato nel passaggio precedente, puoi raggiungere questo obiettivo creando una sequenza temporale di avanzamento di scorrimento anonima con la funzione scroll():

src/styles.css

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  animation-timeline: scroll(nearest inline);
}

Anche se questa porzione di codice potrebbe funzionare, non è dovuto al funzionamento delle ricerche dei container a scorrimento automatico che utilizzano nearest. Quando cerchi lo scorrimento più vicino, l'elemento prende in considerazione solo gli elementi che possono modificarne la posizione. Poiché .gallery__progress è posizionato in modo assoluto, il primo elemento principale che ne determinerà la posizione è l'elemento .gallery, in quanto ha applicato position: relative. Ciò significa che l'elemento .gallery__scrollcontainer, ovvero lo strumento di scorrimento che deve essere scelto come target, non viene considerato durante questa ricerca automatica.

Per ovviare a questo problema, crea una cronologia dell'avanzamento di scorrimento denominata nell'elemento .gallery__scrollcontainer e collega .gallery__progress a quest'ultimo utilizzando questo nome.

Per creare una sequenza temporale dell'avanzamento di scorrimento denominata su un elemento, imposta la proprietà CSS scroll-timeline-name nel contenitore di scorrimento su un valore che preferisci. Il valore deve iniziare con --.

Poiché la galleria scorre orizzontalmente, devi impostare anche la proprietà scroll-timeline-axis. I valori consentiti sono uguali all'argomento <axis> di scroll().

Infine, per collegare l'animazione alla sequenza temporale dell'avanzamento di scorrimento, imposta la proprietà animation-timeline nell'elemento che deve essere animato sullo stesso valore dell'identificatore utilizzato per scroll-timeline-name.

  • Modifica il file styles.css in modo da includere quanto segue:

src/styles.css

.gallery__scrollcontainer {
  /* Create the gallery-is-scrolling timeline */
  scroll-timeline-name: --gallery-is-scrolling;
  scroll-timeline-axis: inline;
}

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  /* Set gallery-is-scrolling as the timeline */
  animation-timeline: --gallery-is-scrolling;
}

Verifica le modifiche

Se tutto è andato bene, ora dovresti avere questo:

In caso contrario, controlla il ramo solution-step-2 del codice.

6. Anima le immagini della galleria quando entrano ed escono dall'area di scorrimento

Configurare una cronologia di avanzamento di visualizzazione in forma anonima

Un buon effetto da aggiungere è la dissolvenza nelle immagini della galleria non appena vengono visualizzate. A questo scopo, puoi utilizzare una sequenza temporale dell'avanzamento.

Per creare una visualizzazione della cronologia dell'avanzamento, puoi utilizzare la funzione view(). I relativi argomenti accettati sono <axis> e <view-timeline-inset>.

  • Il <axis> è lo stesso della sequenza temporale dell'avanzamento di scorrimento e definisce l'asse da monitorare.
  • Con <view-timeline-inset>, puoi specificare un offset (positivo o negativo) per regolare i limiti quando un elemento è considerato visibile o meno.
  • I fotogrammi chiave sono già presenti, quindi devi solo collegarli. Per farlo, crea una sequenza temporale dell'avanzamento della visualizzazione su ogni elemento .gallery__entry.

src/styles.css

@keyframes animate-in {
  from {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  to {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Limitare l'intervallo di una sequenza temporale di avanzamento della visualizzazione

Se salvi il file CSS e carichi la pagina, noterai che gli elementi entrano in dissolvenza, ma qualcosa sembra errato. Iniziano con l'opacità 0 quando sono completamente fuori dalla visuale e terminano con l'opacità 1 solo quando sono completamente uscite.

Questo perché l'intervallo predefinito per una sequenza temporale dell'avanzamento della visualizzazione è l'intero intervallo. Questo è noto come intervallo cover.

  1. Per scegliere come target solo l'intervallo entry del soggetto, utilizza la proprietà CSS animation-range per limitare il momento in cui deve essere eseguita l'animazione.

src/styles.css

.gallery__entry {
  animation: linear fade-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry 0% entry 100%;
}

L'animazione ora va da entry 0% (l'oggetto sta per entrare nello scorrimento) a entry 100% (il soggetto è completamente inserito nello scorrimento).

I possibili intervalli di cronologia delle visualizzazioni sono i seguenti:

  • cover. Rappresenta l'intero intervallo della sequenza temporale di avanzamento della visualizzazione.
  • entry. Rappresenta l'intervallo durante il quale la casella dell'entità entra nell'intervallo di visibilità dell'avanzamento della visualizzazione.
  • exit. Rappresenta l'intervallo durante il quale la casella dell'entità esce dall'intervallo di visibilità dell'avanzamento della visualizzazione.
  • entry-crossing. Rappresenta l'intervallo durante il quale la casella principale attraversa il bordo del bordo finale.
  • exit-crossing. Rappresenta l'intervallo durante il quale la casella dell'entità attraversa il bordo del bordo iniziale.
  • contain. Rappresenta l'intervallo durante il quale la casella dell'entità è contenuta completamente o copre completamente l'intervallo di visibilità dell'avanzamento della visualizzazione all'interno dell'area di scorrimento. Dipende dal fatto che il soggetto sia più alto o più corto dell'autore dello scorrimento.

Utilizza lo strumento all'indirizzo https://goo.gle/view-timeline-range-tool per vedere cosa rappresenta ogni intervallo e come le percentuali influiscono sulle posizioni di inizio e fine.

  1. Poiché gli intervalli di inizio e fine sono gli stessi e vengono utilizzati gli offset predefiniti, semplifica animation-range in modo che includa un singolo nome di intervallo di animazione:

src/styles.css

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry;
}
  • Per applicare una dissolvenza alle immagini quando escono dallo scorrimento, puoi eseguire la stessa operazione dell'animazione con animazione, ma scegliere come target un intervallo diverso.

src/styles.css

@keyframes animate-out {
  from {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  to {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in, linear animate-out;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry, exit;
}

I animate-in fotogrammi chiave verranno applicati all'intervallo entry e i animate-out fotogrammi chiave all'intervallo exit.

Verifica le modifiche

Se tutto è andato bene, ora dovresti avere questo:

In caso contrario, controlla il ramo solution-step-3 del codice.

7. Anima le immagini della galleria quando entrano ed escono dall'area di scorrimento, utilizzando un set di fotogrammi chiave

Il caso di un insieme di fotogrammi chiave

Invece di allegare due animazioni a intervalli diversi, è possibile creare un insieme di fotogrammi chiave che contiene già le informazioni sull'intervallo.

La forma dei fotogrammi chiave è simile alla seguente:

@keyframes keyframes-name {
  range-name range-offset {
    ...
  }
  range-name range-offset {
    ...
  }
}
  1. Combina i fotogrammi chiave di dissolvenza in entrata e in uscita nel seguente modo:

src/styles.css

@keyframes animate-in-and-out {
  entry 0% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  entry 90% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }

  exit 10% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  exit 100% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}
  1. Quando le informazioni sull'intervallo sono presenti nei fotogrammi chiave, non è più necessario specificare animation-range separatamente. Collega i fotogrammi chiave come proprietà animation.

src/styles.css

.gallery__entry {
  animation: linear animate-in-and-out both;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Verifica le modifiche

Se tutto è andato bene, dovresti ottenere lo stesso risultato del passaggio precedente. In caso contrario, controlla il ramo solution-step-4 del codice.

8. Complimenti!

Hai completato questo codelab e ora sai come creare le sequenze temporali dell'avanzamento di scorrimento e visualizzare le sequenze temporali dell'avanzamento in CSS.

Scopri di più

Risorse: