Una panoramica di base su come creare una visualizzazione a scorrimento orizzontale reattiva per TV, smartphone, computer e così via.
In questo post voglio condividere alcune idee su come creare esperienze di scorrimento orizzontale per il web che siano minimaliste, reattive, accessibili e funzionino su browser e piattaforme (come le TV). Prova la demo.
Se preferisci i video, ecco una versione di questo post su YouTube:
Panoramica
Creeremo un layout a scorrimento orizzontale pensato per ospitare le miniature di
contenuti multimediali o prodotti. Il componente inizia come un semplice elenco <ul>
, ma viene trasformato con CSS in un'esperienza di scorrimento soddisfacente e fluida, che mostra le immagini e le aggancia a una griglia. JavaScript viene aggiunto per facilitare
le interazioni con l'indice mobile, aiutando gli utenti della tastiera a evitare di attraversare più di 100 elementi.
Inoltre, viene utilizzata una media query sperimentale, prefers-reduced-data
, per trasformare lo
scorrimento dei contenuti multimediali in un'esperienza di scorrimento dei titoli leggera.
Inizia con il markup accessibile
Uno scorrimento multimediale è composto da un paio di componenti principali, un elenco con elementi. Una lista, nella sua forma più semplice, può viaggiare in tutto il mondo ed essere chiaramente compresa da tutti. Un utente che arriva a questa pagina può sfogliare un elenco e fare clic su un link per visualizzare un articolo. Questa è la nostra base accessibile.
Fornisci un elenco con un elemento <ul>
:
<ul class="horizontal-media-scroller">
<li></li>
<li></li>
<li></li>
...
<ul>
Rendi interattivi gli elementi dell'elenco con un elemento <a>
:
<li>
<a href="#">
...
</a>
</li>
Utilizza un elemento <figure>
per rappresentare semanticamente un'immagine e la relativa didascalia:
<figure>
<picture>
<img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
</picture>
<figcaption>Legends</figcaption>
</figure>
Nota gli attributi alt
e loading
in <img>
. Il testo alternativo per uno scroller multimediale è un'opportunità UX per fornire un contesto aggiuntivo alla miniatura o come testo di riserva se l'immagine non è stata caricata. Inoltre, fornisce un'interfaccia utente vocale per gli utenti che si affidano a tecnologie assistive come uno screen reader. Scopri di più con le cinque regole
d'oro per un testo
alternativo conforme.
L'attributo loading
accetta la parola chiave lazy
per indicare che l'origine di questa immagine
deve essere recuperata solo quando l'immagine si trova all'interno della finestra. Questa funzionalità può essere
molto utile per gli elenchi di grandi dimensioni, in quanto gli utenti scaricheranno solo le immagini degli elementi che
hanno visualizzato.
Supportare la preferenza della combinazione di colori dell'utente
Utilizza color-scheme
come tag <meta>
per segnalare al browser che la tua pagina
vuole gli stili user agent forniti sia per la modalità Luce che per la modalità Buio. È una modalità Buio
o una modalità Chiaro senza costi, a seconda di come la vedi:
<meta name="color-scheme" content="dark light">
Il metatag fornisce il segnale più tempestivo possibile, in modo che il browser possa selezionare un colore di sfondo scuro predefinito se l'utente ha una preferenza per il tema scuro. Ciò significa che la navigazione tra le pagine del sito non mostrerà uno sfondo bianco tra un caricamento e l'altro. Tema scuro fluido tra i caricamenti, molto più piacevole per gli occhi.
Scopri di più da Thomas Steiner all'indirizzo https://web.dev/color-scheme/.
Aggiungi contenuti
Data la struttura dei contenuti di ul > li > a > figure > picture > img
riportata sopra,
il passaggio successivo consiste nell'aggiungere immagini e titoli da scorrere. Ho inserito nella demo immagini e testo segnaposto statici, ma puoi utilizzare la tua origine dati preferita.
Aggiungere stile con CSS
Ora è il momento che il CSS prenda questo elenco generico di contenuti e lo trasformi in un'esperienza. Netflix, gli app store e molti altri siti e app utilizzano aree di scorrimento orizzontale per riempire il riquadro con categorie e opzioni.
Creazione del layout dello scorrimento
È importante evitare di tagliare i contenuti nei layout o di affidarsi al troncamento del testo con i puntini di sospensione. Molti televisori hanno dei selettori multimediali come questo, ma troppo spesso ricorrono all'ellissi per i contenuti. Questo layout no. Consente inoltre ai contenuti multimediali di ignorare le dimensioni della colonna, rendendo un layout abbastanza flessibile da gestire molte combinazioni interessanti.
Il contenitore consente di ignorare le dimensioni della colonna fornendo le dimensioni predefinite come proprietà personalizzata. Questo layout a griglia è orientato alle dimensioni delle colonne, in quanto gestisce solo la spaziatura e la direzione:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2); /* parent owned value for children to be relative to*/
margin: 0;
}
La proprietà personalizzata viene quindi utilizzata dall'elemento <picture>
per creare le proporzioni di base: un riquadro:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
& picture {
inline-size: var(--size);
block-size: var(--size);
}
}
Con solo alcuni stili secondari, completa la struttura di base dello scorrimento dei contenuti multimediali:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
& > li {
display: inline-block; /* removes the list-item bullet */
}
& picture {
inline-size: var(--size);
block-size: var(--size);
}
}
L'impostazione overflow
configura <ul>
in modo da consentire lo scorrimento e la navigazione da tastiera
nell'elenco, quindi a ogni elemento secondario diretto <li>
viene rimosso ::marker
assegnando un nuovo tipo di visualizzazione inline-block
.
Le immagini non sono ancora responsive e escono direttamente dalle caselle in cui si trovano. Domali con dimensioni, adattamento e stili del bordo e un gradiente di sfondo per il caricamento differito:
img {
/* smash into whatever box it's in */
inline-size: 100%;
block-size: 100%;
/* don't squish but do cover the space */
object-fit: cover;
/* soften the edges */
border-radius: 1ex;
overflow: hidden;
/* if empty, show a gradient placeholder */
background-image:
linear-gradient(
to bottom,
hsl(0 0% 40%),
hsl(0 0% 20%)
);
}
Spaziatura interna di scorrimento
L'allineamento ai contenuti della pagina e una superficie di scorrimento da bordo a bordo sono fondamentali per un componente armonioso e minimalista.
Per ottenere il layout di scorrimento da bordo a bordo in linea con la nostra tipografia
e le nostre linee di layout, utilizza padding
che corrisponde a scroll-padding
:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding-inline: var(--gap);
scroll-padding-inline: var(--gap);
padding-block: calc(var(--gap) / 2); /* make space for scrollbar and focus outline */
}
Correzione del bug del padding di scorrimento orizzontale L'esempio precedente mostra la facilità con cui è possibile aggiungere padding a un contenitore di scorrimento, ma esistono problemi di compatibilità in sospeso (risolti in Chromium 91 e versioni successive). Consulta questa pagina per un po' di storia, ma la versione breve è che il padding non è sempre stato preso in considerazione in una visualizzazione a scorrimento.
Per indurre i browser a inserire il padding alla fine dello scorrimento, selezionerò l'ultima cifra di ogni elenco e aggiungerò uno pseudo elemento che corrisponde alla quantità di padding desiderata.
.horizontal-media-scroller > li:last-of-type figure {
position: relative;
&::after {
content: "";
position: absolute;
inline-size: var(--gap);
block-size: 100%;
inset-block-start: 0;
inset-inline-end: calc(var(--gap) * -1);
}
}
L'utilizzo di proprietà logiche consente allo scorrimento dei contenuti multimediali di funzionare in qualsiasi modalità di scrittura e direzione del documento.
Allineamento dello scorrimento
Un contenitore scorrevole con overflow può diventare una finestra di visualizzazione con snapping con una riga di CSS, quindi spetta ai figli specificare come vogliono allinearsi a quella finestra di visualizzazione.
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding-inline: var(--gap);
scroll-padding-inline: var(--gap);
padding-block-end: calc(var(--gap) / 2);
scroll-snap-type: inline mandatory;
& figure {
scroll-snap-align: start;
}
}
Concentrazione
L'ispirazione per questo componente deriva dalla sua enorme popolarità su TV, store di app e altro ancora. Molte piattaforme di videogiochi utilizzano uno scorrimento dei contenuti multimediali molto simile a questo come layout principale della schermata Home. La messa a fuoco è un elemento fondamentale dell'esperienza utente, non solo una piccola aggiunta. Immagina di utilizzare questo selettore multimediale dal divano con un telecomando e di apportare alcuni piccoli miglioramenti all'interazione:
.horizontal-media-scroller a {
outline-offset: 12px;
&:focus {
outline-offset: 7px;
}
@media (prefers-reduced-motion: no-preference) {
& {
transition: outline-offset .25s ease;
}
}
}
In questo modo, lo stile del contorno della messa a fuoco 7px
viene spostato lontano dalla casella, lasciando un po' di spazio. Se l'utente non ha preferenze di movimento per la riduzione del movimento, l'offset
viene spostato, dando un movimento sottile all'evento di messa a fuoco.
Indice mobile
Gli utenti di gamepad e tastiera richiedono un'attenzione particolare in queste lunghe liste di contenuti e opzioni scorrevoli. Il modello comune per risolvere questo problema è chiamato indice mobile. Si verifica quando un contenitore di elementi è attivo con la tastiera, ma solo un elemento secondario può essere attivo alla volta. Questa esperienza di messa a fuoco di un solo elemento alla volta è progettata per consentire di ignorare l'elenco potenzialmente lungo di elementi, anziché premere il tasto Tab più di 50 volte per raggiungere la fine.
Nel primo scroller della demo ci sono 300 elementi. Possiamo fare di meglio che farli attraversare tutte le sezioni per raggiungere quella successiva.
Per creare questa esperienza, JavaScript deve osservare gli eventi della tastiera e gli eventi di messa a fuoco. Ho creato una piccola libreria open source su npm per semplificare questa esperienza utente. Ecco come utilizzarlo per i tre selettori:
import {rovingIndex} from 'roving-ux';
rovingIndex({
element: someElement
});
Questa demo esegue query sul documento per gli scorrimenti e per ognuno di essi chiama la funzione
rovingIndex()
. Passa rovingIndex()
all'elemento per ottenere l'esperienza di spostamento
dello stato attivo, come un contenitore di elenco, e un selettore di query di destinazione, nel caso in cui
i target dello stato attivo non siano discendenti diretti.
document.querySelectorAll('.horizontal-media-scroller')
.forEach(scroller =>
rovingIndex({
element: scroller,
target: 'a',
}))
Per saperne di più su questo effetto, consulta la libreria open source roving-ux.
Proporzioni
Al momento della stesura di questo post, il supporto di
aspect-ratio
è disponibile in Firefox tramite un
flag, ma è disponibile nei browser Chromium o nei set-top box. Poiché il layout a griglia dello scorrimento dei contenuti multimediali specifica solo la direzione e la spaziatura, le dimensioni possono cambiare all'interno di una media query, la cui funzionalità verifica il supporto delle proporzioni.
Miglioramento progressivo di alcuni scorrimenti di contenuti multimediali più dinamici.
@supports (aspect-ratio: 1) {
.horizontal-media-scroller figure > picture {
inline-size: auto; /* for a block-size driven ratio */
aspect-ratio: 1; /* boxes by default */
@nest section:nth-child(2) & {
aspect-ratio: 16/9;
}
@nest section:nth-child(3) & {
/* double the size of the others */
block-size: calc(var(--size) * 2);
aspect-ratio: 4/3;
/* adjust size to fit more items into the viewport */
@media (width <= 480px) {
block-size: calc(var(--size) * 1.5);
}
}
}
}
Se il browser supporta la sintassi aspect-ratio
, le immagini dello scorrimento dei contenuti multimediali vengono
aggiornate al dimensionamento aspect-ratio
. Utilizzando la sintassi di nidificazione delle bozze, ogni immagine
cambia le proporzioni a seconda che si trovi nella prima, nella seconda o nella terza riga. La
sintassi nidificata consente anche di impostare piccoli
aggiustamenti della finestra, insieme all'altra logica di dimensionamento.
Con questo CSS, man mano che la funzionalità sarà disponibile in più motori del browser, verrà visualizzato un layout facile da gestire ma più accattivante dal punto di vista visivo.
Preferenza per la riduzione dei dati
Anche se questa tecnica è disponibile solo dietro un flag in Canary, volevo condividere come ho potuto risparmiare una notevole quantità di tempo di caricamento della pagina e di utilizzo dei dati con poche righe di CSS. La media query prefers-reduced-data
del
livello 5 consente di verificare se il dispositivo si trova in
uno stato di riduzione dei dati, ad esempio una modalità di risparmio dati. Se è così, posso modificare il
documento e, in questo caso, nascondere le immagini.
figure {
@media (prefers-reduced-data: reduce) {
& {
min-inline-size: var(--size);
& > picture {
display: none;
}
}
}
}
I contenuti sono ancora navigabili, ma senza il costo del download delle immagini pesanti. Ecco il sito prima di aggiungere il CSS prefers-reduced-data
:
(7 richieste, 100 KB di risorse in 131 ms)
Ecco il rendimento del sito dopo l'aggiunta del CSS prefers-reduced-data
:
(71 richieste, 1,2 MB di risorse in 1,07 secondi)
64 richieste in meno, ovvero circa 60 immagini all'interno del riquadro visibile (test eseguiti su un display widescreen) di questa scheda del browser, un aumento del caricamento della pagina di circa l'80% e il 10% dei dati via cavo. CSS piuttosto potente.
Conclusione
Ora che sai come ho fatto, come faresti tu? 🙂
Diversifichiamo i nostri approcci e impariamo tutti i modi per creare sul web. Crea un Codepen o ospita la tua demo, inviami un tweet e la aggiungerò alla sezione Remix della community di seguito.
Origine
Remix della community
Ancora nessun elemento da visualizzare.