Creare un componente Storie

Una panoramica di base su come creare un'esperienza simile alle Storie di Instagram sul web.

In questo post voglio condividere il mio pensiero sulla creazione di un componente Storie per il web che sia reattivo, supporti la navigazione da tastiera e funzioni su tutti i browser.

Demo

Se preferisci una dimostrazione pratica della creazione di questo componente Storie, consulta il codelab sul componente Storie.

Se preferisci i video, ecco una versione di questo post su YouTube:

Panoramica

Due esempi popolari di UX delle storie sono le storie di Snapchat e le storie di Instagram (per non parlare dei fleet). In termini di UX, le storie sono in genere un pattern basato sui tocchi e disponibile solo sui dispositivi mobili per navigare tra più abbonamenti. Ad esempio, su Instagram gli utenti aprono la storia di un amico e sfogliano le immagini al suo interno. In genere, lo fanno con molti amici contemporaneamente. Se tocca il lato destro del dispositivo, l'utente passa alla storia successiva dell'amico. Se scorre verso destra, l'utente passa a un altro amico. Un componente Storia è abbastanza simile a un carosello, ma consente di navigare in un array multidimensionale anziché in un array unidimensionale. È come se ci fosse un carosello all'interno di ogni carosello. 🤯

Visualizzazione di un array multidimensionale utilizzando le schede. Da sinistra a destra, c'è una pila di schede con bordi viola e all'interno di ogni scheda ci sono da 1 a molte schede con bordi ciano. Elenco in un elenco.
1° carosello di amici
2° carosello "impilato" di storie
👍 Elenco in un elenco, ovvero un array multidimensionale

Scegliere gli strumenti giusti per il lavoro

Nel complesso, ho trovato questo componente piuttosto semplice da creare, grazie ad alcune funzionalità critiche della piattaforma web. Vediamoli insieme.

Griglia CSS

Il nostro layout non è risultato difficile da realizzare con CSS Grid, che è dotato di alcuni strumenti potenti per gestire i contenuti.

Layout di Friends

Il wrapper del componente .stories principale è una visualizzazione a scorrimento orizzontale con priorità ai contenuti per dispositivi mobili:

.stories {
  inline-size: 100vw;
  block-size: 100vh;

  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;

  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}

/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
  max-inline-size: 480px;
  max-block-size: 848px;
}
Utilizzo della modalità dispositivo di Chrome DevTools per evidenziare le colonne create da Griglia

Analizziamo il layout grid:

  • Riempiamo esplicitamente l'area visibile sui dispositivi mobili con 100vh e 100vw e limitiamo le dimensioni sul computer
  • / separa i nostri modelli di righe e colonne
  • auto-flow si traduce in grid-auto-flow: column
  • Il modello di flusso automatico è 100%, che in questo caso corrisponde alla larghezza della finestra di scorrimento

Su un cellulare, pensa a questo come se le dimensioni della riga fossero l'altezza del viewport e ogni colonna fosse la larghezza del viewport. Continuando con l'esempio delle storie di Snapchat e Instagram, ogni colonna sarà la storia di un amico. Vogliamo che le storie degli amici continuino al di fuori dell'area visibile, in modo da avere qualcosa da scorrere. Grid creerà il numero di colonne necessario per disporre l'HTML per ogni storia dell'amico, creando un contenitore di scorrimento dinamico e reattivo. Grid ci ha permesso di centralizzare l'intero effetto.

Stacking

Per ogni amico, abbiamo bisogno delle sue storie in uno stato pronto per la paginazione. In preparazione all'animazione e ad altri pattern divertenti, ho scelto una pila. Quando dico pila, intendo come se stessi guardando un panino dall'alto, non di lato.

Con la griglia CSS, possiamo definire una griglia a una sola cella (ovvero un quadrato), in cui le righe e le colonne condividono un alias ([story]), e poi a ogni elemento secondario viene assegnato quello spazio alias a una sola cella:

.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.story {
  grid-area: story;
  background-size: cover;
  
}

In questo modo, il nostro HTML controlla l'ordine di impilamento e mantiene anche tutti gli elementi in flusso. Nota come non abbiamo dovuto fare nulla con il posizionamento absolute o z-index e non abbiamo dovuto correggere la posizione con height: 100% o width: 100%. La griglia principale ha già definito le dimensioni dell'area visibile dell'immagine della storia, quindi nessuno di questi componenti della storia doveva essere impostato per riempirla.

Punti di snap dello scorrimento CSS

La specifica CSS Scroll Snap Points consente di bloccare facilmente gli elementi nell'area visibile durante lo scorrimento. Prima che esistessero queste proprietà CSS, era necessario utilizzare JavaScript, ed era… complicato, a dir poco. Consulta l'articolo Introducing CSS Scroll Snap Points di Sarah Drasner per una spiegazione dettagliata di come utilizzarli.

Scorrimento orizzontale senza e con stili scroll-snap-points. Senza, gli utenti possono scorrere liberamente come di consueto. In questo modo, il browser si posiziona delicatamente su ogni elemento.
principale
.stories {
  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}
Il genitore con overscroll definisce il comportamento di snap.
bambino
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
I bambini scelgono di diventare un bersaglio degli snap.

Ho scelto i punti di scorrimento per diversi motivi:

  • Accessibilità senza costi. La specifica Punti di scorrimento indica che la pressione dei tasti Freccia sinistra e Freccia destra dovrebbe spostarsi tra i punti di scorrimento per impostazione predefinita.
  • Una specifica in crescita. La specifica Scroll Snap Points riceve continuamente nuove funzionalità e miglioramenti, il che significa che il mio componente Storie probabilmente migliorerà sempre di più.
  • Facilità di implementazione. I punti di scorrimento sono praticamente pensati per il caso d'uso della paginazione orizzontale incentrata sul tocco.
  • Inerzia senza costi in stile piattaforma. Ogni piattaforma scorrerà e si fermerà nel proprio stile, a differenza dell'inerzia normalizzata, che può avere uno stile di scorrimento e arresto innaturale.

Compatibilità cross-browser

Abbiamo eseguito i test su Opera, Firefox, Safari e Chrome, oltre che su Android e iOS. Ecco un breve riepilogo delle funzionalità web in cui abbiamo riscontrato differenze in termini di funzionalità e supporto.

Tuttavia, alcuni CSS non sono stati applicati, quindi alcune piattaforme non beneficiano attualmente delle ottimizzazioni dell'esperienza utente. Mi è piaciuto non dover gestire queste funzionalità e sono sicuro che alla fine arriveranno su altri browser e piattaforme.

scroll-snap-stop

I caroselli sono stati uno dei principali casi d'uso dell'esperienza utente che hanno portato alla creazione della specifica CSS Scroll Snap Points. A differenza delle storie, un carosello non deve sempre fermarsi su ogni immagine dopo l'interazione di un utente. Potrebbe essere accettabile o incoraggiato scorrere rapidamente il carosello. Le storie, invece, vanno navigate una alla volta ed è esattamente ciò che offre scroll-snap-stop.

.user {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

Al momento della stesura di questo post, scroll-snap-stop è supportato solo sui browser basati su Chromium. Consulta la sezione Compatibilità del browser per gli aggiornamenti. Tuttavia, non è un blocco. Significa solo che sui browser non supportati gli utenti possono saltare accidentalmente un amico. Quindi gli utenti dovranno fare più attenzione oppure dovremo scrivere JavaScript per assicurarci che un amico saltato non venga contrassegnato come visualizzato.

Se ti interessa, scopri di più nelle specifiche.

overscroll-behavior

Ti è mai capitato di scorrere una finestra modale e improvvisamente iniziare a scorrere i contenuti dietro la finestra modale? overscroll-behavior consente allo sviluppatore di bloccare lo scorrimento e non lasciarlo mai andare via. È adatto a ogni tipo di occasione. Il componente Le mie storie lo utilizza per impedire che ulteriori scorrimenti e gesti di scorrimento escono dal componente.

.stories {
  overflow-x: auto;
  overscroll-behavior: contain;
}

Safari e Opera sono i due browser che non supportano questa funzionalità, il che è assolutamente normale. Questi utenti avranno un'esperienza di overscroll come al solito e potrebbero non notare mai questo miglioramento. Personalmente, sono un grande fan e mi piace includerlo in quasi tutte le funzionalità di overscroll che implemento. È un'aggiunta innocua che può solo portare a una migliore esperienza utente.

scrollIntoView({behavior: 'smooth'})

Quando un utente tocca o fa clic e ha raggiunto la fine del set di storie di un amico, è il momento di passare all'amico successivo nel set di punti di scorrimento. Con JavaScript, siamo riusciti a fare riferimento all'amico successivo e a richiedere che venga visualizzato. Il supporto per le basi è ottimo: ogni browser lo ha visualizzato. Tuttavia, non tutti i browser lo hanno fatto 'smooth'. Ciò significa semplicemente che è stato visualizzato tramite scorrimento anziché tramite snap.

element.scrollIntoView({
  behavior: 'smooth'
})

Safari era l'unico browser a non supportare behavior: 'smooth' qui. Consulta la sezione Compatibilità del browser per gli aggiornamenti.

Pratico

Ora che sai come ho fatto, come faresti tu? Diversifichiamo i nostri approcci e impariamo tutti i modi per creare contenuti sul web. Crea un Glitch, inviami un tweet con la tua versione e la aggiungerò alla sezione Remix della community di seguito.

Remix della community