Creare un componente Storie

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

In questo post vorrei parlare della creazione di un componente Storie per il web che sia reattivo, che supporti la navigazione da tastiera e funzioni su più browser.

Demo

Se preferisci una dimostrazione pratica su come creare in autonomia il componente Storie, dai un'occhiata al codelab del componente Storie.

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

Panoramica

Due esempi popolari di esperienza utente delle Storie sono le Storie Snapchat e le Storie Instagram (per non parlare dei parchi risorse). In termini generali relativi all'esperienza utente, le Storie prevedono di solito uno schema incentrato solo sui dispositivi mobili per la navigazione di più abbonamenti. Ad esempio, su Instagram gli utenti aprono la storia di un amico e sfogliano le foto in essa contenute. Di solito fanno così tanti amici alla volta. Toccando il lato destro del dispositivo, l'utente passa alla storia successiva dell'amico. Scorrendo verso destra, l'utente passa a un altro amico. Un componente Storia è abbastanza simile a un carosello, ma consente la navigazione in un array multidimensionale anziché in un array monodimensionale. È come se ci fosse un carosello all'interno di ogni carosello. 🤯

Array multidimensionale visualizzato utilizzando le schede. Da sinistra a destra c'è una pila di schede con bordi viola e all'interno di ogni scheda ci sono una serie di schede con bordi ciano. Elenco.
Primo carosello di amici
Secondo carosello di storie "impilate"
👍 Elenco in un elenco, anche noto come array multidimensionale

Scegliere gli strumenti giusti per il lavoro

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

Griglia CSS

Il nostro layout si è rivelato poco efficace per la griglia CSS, in quanto è dotata di modalità efficaci per eseguire il data wrangling dei contenuti.

Layout degli amici

Il nostro wrapper principale del componente .stories è una visualizzazione con scorrimento orizzontale orientata ai 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 di Chrome DevTools Modalità dispositivo per evidenziare le colonne create dalla griglia

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, la dimensione della riga potrebbe essere l'altezza dell'area visibile e la larghezza dell'area visibile per ogni colonna. Proseguendo con gli esempi Storie di Snapchat e Storie Instagram, ogni colonna riporta la storia di un amico. Vogliamo che le storie degli amici continuino a rimanere al di fuori dell'area visibile, in modo da avere un punto in cui scorrere. La griglia creerà tutte le colonne necessarie per il layout del tuo codice HTML per ogni storia di amicizia, creando per noi un contenitore a scorrimento dinamico e adattabile. La griglia ci ha permesso di centralizzare l'intero effetto.

Impilamento

Per ogni amico, abbiamo bisogno che le loro storie siano pronte per l'impaginazione. Per preparare l'animazione e altri motivi divertenti, ho scelto uno stack. Quando dico pila, stai guardando un panino, non come se stessi guardando un lato.

Con la griglia CSS, possiamo definire una griglia a cella singola (ad es. un quadrato), in cui le righe e le colonne condividono un alias ([story]) e 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 il codice HTML avrà il controllo dell'ordine di sovrapposizione e il flusso di tutti gli elementi sarà sempre attivo. Come puoi notare, non dovevamo fare nulla con il posizionamento absolute o z-index e non dovevamo effettuare la correzione con height: 100% o width: 100%. La griglia principale definiva già le dimensioni dell'area visibile dell'immagine della storia, quindi non è stato necessario indicare nessuno di questi componenti della storia per riempirla.

Punti di aggancio di scorrimento CSS

La specifica Snap Points di scorrimento CSS consente di bloccare elementi nell'area visibile durante lo scorrimento. Prima che esistessero queste proprietà CSS, bisognava usare JavaScript ed era... difficile, a dir poco. Dai un'occhiata al documento Presentazione dei punti Snap di scorrimento CSS di Sarah Drasner per un'analisi dettagliata di come utilizzarli.

Scorrimento orizzontale senza e con stili scroll-snap-points. Senza di esso, gli utenti possono liberare lo scorrimento come di consueto. che consente al browser di poggiare delicatamente su ogni elemento.
parent
.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 scorrimento orizzontale definisce il comportamento di agganciamento.
bambino/bambina
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
I minori scelgono di essere un bersaglio rapido.

Ho scelto i punti di aggancio di scorrimento per alcuni motivi:

  • Accessibilità senza costi. La specifica dei punti di agganciamento di scorrimento indica che per impostazione predefinita i tasti Freccia sinistra e Freccia destra devono spostarsi tra i punti di agganciamento.
  • Una specifica in continua crescita. La specifica dei punti Snap di scorrimento riceve costantemente nuove funzionalità e miglioramenti, il che significa che il mio componente Storie probabilmente migliorerà solo da qui in poi.
  • Facilità di implementazione. Gli Snap Points sono realizzati in pratica per il caso d'uso della paginazione orizzontale incentrata sul tocco.
  • Inerzia libera a livello di piattaforma. Ogni piattaforma scorrerà e si fermerà nel suo stile, al contrario dell'inerzia normalizzata, che può avere uno stile di scorrimento e riposo incredibilmente incredibilmente.

Compatibilità tra browser

Abbiamo eseguito il test su Opera, Firefox, Safari e Chrome, oltre ad Android e iOS. Ecco un breve resoconto delle funzionalità web in cui abbiamo riscontrato differenze nelle funzionalità e nell'assistenza.

Poiché alcuni CSS non sono stati applicati, alcune piattaforme stanno perdendo opportunità di ottimizzazione dell'esperienza utente. È stato fantastico non dover gestire queste funzionalità e ho la certezza che arriveranno ad altri browser e piattaforme.

scroll-snap-stop

I caroselli sono stati uno dei principali casi d'uso di UX che hanno portato alla creazione della specifica dei punti Snap di scorrimento CSS. A differenza delle storie, un carosello non deve sempre fermarsi su ogni immagine dopo che l'utente ha interagito con essa. Potrebbe andare bene o essere incoraggiato a scorrere velocemente il carosello. D'altra parte, è meglio consultarle 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. Verifica la compatibilità del browser per eventuali aggiornamenti. Ma non è un blocco. Significa solo che su browser non supportati gli utenti possono saltare accidentalmente un amico. Quindi gli utenti dovranno fare solo maggiore attenzione o dovremo scrivere codice JavaScript per garantire che un amico ignorato non venga contrassegnato come visualizzato.

Se ti interessa, leggi di più nelle specifiche.

overscroll-behavior

Ti è mai capitato di scorrere una finestra modale quando all'improvviso inizi a scorrere i contenuti dietro la finestra modale? overscroll-behavior consente allo sviluppatore di bloccare i contenuti che scorre e non lasciarli mai abbandonare. È perfetto per ogni occasione. Il componente Le mie storie lo utilizza per impedire che altri gesti di scorrimento e altri gesti di scorrimento escano dal componente.

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

Safari e Opera erano i due browser che non lo supportavano e questo è assolutamente normale. Questi utenti usufruiranno di un'esperienza di scorrimento orizzontale come sono abituati e potrebbero non notare mai questo miglioramento. Personalmente, sono una grande fan e mi piace includerla in quasi tutte le funzionalità di scorrimento orizzontale che implemento. È un'aggiunta innocua che può solo portare a una migliore UX.

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 inserimento di scorrimento. Con JavaScript, siamo stati in grado di fare riferimento all'amico successivo e di richiedere che venga visualizzato tramite scorrimento. Il supporto per le basi è eccezionale; ogni browser lo ha reso visibile. Tuttavia, l'esecuzione di questa operazione non è stata eseguita da tutti i browser 'smooth'. Ciò significa solo che l'elemento è stato reso visibile tramite scorrimento anziché agganciato.

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

Safari è l'unico browser a non supportare behavior: 'smooth' qui. Verifica la compatibilità del browser per eventuali aggiornamenti.

Pratico

Ora che sai come ci sono riuscito, come faresti?! Diversifica i nostri approcci e impariamo tutti i modi per creare sul web. Crea un Glitch, inviaci un tweet con la tua versione e lo aggiungerò alla sezione Remix della community di seguito.

Remix della community