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 alcune riflessioni sulla creazione di un componente Storie per il web che sia adattabile, 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 generali di UX, le storie sono solitamente un pattern incentrato sul tocco, disponibile solo su dispositivi mobili, per navigare tra più abbonamenti. Ad esempio, su Instagram, gli utenti aprono la storia di un amico e scorrono le immagini al suo interno. In genere lo fanno con molti amici alla volta. Toccando il lato destro del dispositivo, un utente passa alla storia successiva di quell'amico. Scorrendo verso destra, un 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. 🤯

Array multidimensionale visualizzato utilizzando le schede. Da sinistra a destra, una serie di schede con bordi viola, ognuna delle quali contiene una o più schede con bordi ciano. Elenco in un elenco.
1° carosello di amici
2° carosello "in pila" di storie
👍 Elenco in un elenco, ovvero un array multidimensionale

Scegliere gli strumenti giusti per il lavoro

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

Griglia CSS

Il nostro layout non è stato un problema per CSS Grid, in quanto è dotato di alcuni modi efficaci per gestire i contenuti.

Layout Amici

Il nostro wrapper principale dei componenti .stories è una visualizzazione a scorrimento orizzontale pensata per i 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 Grid

Analizziamo il layout grid:

  • Riempiamo esplicitamente l'area visibile sui dispositivi mobili con 100vh e 100vw e limitiamo le dimensioni sui computer
  • / separa i nostri modelli di riga e colonna
  • 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, immagina che la dimensione della riga sia l'altezza dell'area visibile e che ogni colonna sia la larghezza dell'area visibile. 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 della visualizzazione, in modo da avere un punto in cui scorrere. La griglia creerà il numero di colonne necessarie per il layout del codice HTML per ogni storia degli amici, creando un container di scorrimento dinamico e adattabile. Grid ci ha permesso di centralizzare l'intero effetto.

Stacking

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

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

.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, l'HTML controlla l'ordine di sovrapposizione e mantiene tutti gli elementi nel flusso. Nota come non abbiamo dovuto fare nulla con il posizionamento di absolute o z-index e non abbiamo dovuto correggere il riquadro con height: 100% o width: 100%. La griglia principale ha già definito le dimensioni dell'area visibile dell'immagine della storia, quindi non è stato necessario indicare a nessuno di questi componenti della storia di riempirla.

Punti di ancoraggio dello scorrimento CSS

La specifica CSS Scroll Snap Points semplifica il blocco degli elementi nell'area visibile durante lo scorrimento. Prima dell'esistenza di queste proprietà CSS, dovevi utilizzare JavaScript, il che era… a dir poco complicato. Consulta l'articolo Introducing CSS Scroll Snap Points di Sarah Drasner per un'ottima analisi di come utilizzarli.

Scorrimento orizzontale senza e con gli stili scroll-snap-points. Senza questo attributo, gli utenti possono scorrere liberamente come di consueto. Con questa modalità, il browser si sofferma 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;
}
L'elemento principale con overscroll definisce il comportamento di aggancio.
bambino
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
I bambini scelgono di essere un target di aggancio.

Ho scelto Scroll Snap Points per alcuni motivi:

  • Accessibilità senza costi. La specifica Scroll Snap Points indica che la pressione dei tasti Freccia sinistra e Freccia destra dovrebbe spostarsi tra i punti di aggancio per impostazione predefinita.
  • Una specifica in crescita. La specifica dei punti di aggancio dello scorrimento viene costantemente aggiornata con nuove funzionalità e miglioramenti, il che significa che il mio componente Storie probabilmente migliorerà solo da qui in poi.
  • Facilità di implementazione. I punti di allineamento dello scorrimento sono praticamente progettati per il caso d'uso dell'impaginazione orizzontale incentrata sul tocco.
  • Inerzia libera in stile piattaforma. Ogni piattaforma scorrerà e si fermerà nel suo stile, a differenza dell'inerzia normalizzata che può avere uno stile di scorrimento e di arresto insolito.

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 assistenza.

Tuttavia, alcuni CSS non sono stati applicati, quindi alcune piattaforme non usufruiscono attualmente delle ottimizzazioni della UX. Mi è piaciuto non dover gestire queste funzionalità e sono fiducioso che alla fine raggiungeranno altri browser e piattaforme.

scroll-snap-stop

I caroselli sono stati uno dei principali casi d'uso della UX che hanno portato alla creazione della specifica CSS Scroll Snap Points. A differenza delle storie, un carosello non deve necessariamente fermarsi su ogni immagine dopo che un utente interagisce con questa. Potrebbe essere accettabile o consigliabile scorrere rapidamente il carosello. Le storie, invece, si leggono meglio 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 solo fare più attenzione oppure dovremo scrivere un codice JavaScript per assicurarci che un amico saltato non venga contrassegnato come visualizzato.

Se ti interessa, scopri di più nella specifica.

overscroll-behavior

Ti è mai capitato di scorrere una finestra modale e, all'improvviso, di iniziare a scorrere i contenuti dietro la finestra modale? overscroll-behavior consente allo sviluppatore di intercettare lo scorrimento e di non lasciarlo mai uscire. È perfetto per ogni occasione. Il componente Le mie storie lo utilizza per impedire che ulteriori scorrimenti e gesti di scorrimento escano dal componente.

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

Safari e Opera erano i due browser che non lo supportavano, il che va benissimo. Questi utenti avranno un'esperienza di overscroll come quella a cui sono abituati e potrebbero non notare mai questo miglioramento. Personalmente, sono un grande fan di questa funzionalità e mi piace includerla in quasi tutte le funzionalità di overscroll che implemento. Si tratta di un'aggiunta innocua che può solo portare a una UX migliore.

scrollIntoView({behavior: 'smooth'})

Quando un utente tocca o fa clic e ha raggiunto la fine dell'insieme di storie di un amico, è il momento di passare all'amico successivo nell'insieme di punti di allineamento dello scorrimento. Con JavaScript, siamo riusciti a fare riferimento all'amico successivo e a richiedere che venisse visualizzato tramite scorrimento. Il supporto per le nozioni di base è ottimo; ogni browser lo ha fatto scorrere nella visualizzazione. Tuttavia, non tutti i browser lo hanno fatto 'smooth'. Ciò significa che l'elemento viene visualizzato tramite scorrimento anziché essere agganciato.

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

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

Pratica

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

Remix della community