Créer un composant de défilement multimédia

Présentation générale de la création d'une vue à défilement horizontal responsive pour les téléviseurs, les téléphones, les ordinateurs de bureau, etc.

Dans cet article, je vais vous expliquer comment créer un défilement horizontal. des expériences Web minimales, réactives, accessibles et qui fonctionnent sur des navigateurs et des plates-formes (comme les téléviseurs !). Essayez le demo.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Démonstration

Si vous préférez la vidéo, voici une version YouTube de cet article:

Présentation

Nous allons créer une mise en page à défilement horizontal pour héberger les vignettes de médias ou produits. Au départ, le composant est une simple liste <ul>, mais il est transformées par CSS en une expérience de défilement fluide et satisfaisante, des images et les ancrer à une grille. JavaScript est ajouté pour faciliter Interactions avec un indice temporaire permettant aux utilisateurs de claviers d'éviter de parcourir plus de 100 éléments. De plus, une requête média expérimentale, prefers-reduced-data, permet de transformer en une expérience de défilement de titre légère.

Commencez par un balisage accessible

Un conteneur de défilement multimédia est composé de quelques composants principaux, à savoir une liste d'éléments. A dans sa forme la plus simple, peuvent voyager dans le monde entier et être clairement consommée par tous. Un utilisateur qui accède à cette page peut parcourir une liste et cliquer sur un lien pour afficher un article. C'est notre base accessible.

Diffusez une liste avec un élément <ul>:

<ul class="horizontal-media-scroller">
  <li></li>
  <li></li>
  <li></li>
  ...
<ul>

Rendez les éléments de la liste interactifs avec un élément <a>:

<li>
  <a href="#">
    ...
  </a>
</li>

Utilisez un élément <figure> pour représenter sémantiquement une image et sa légende:

<figure>
  <picture>
    <img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
  </picture>
  <figcaption>Legends</figcaption>
</figure>

Notez les attributs alt et loading sur <img>. Texte alternatif d'un contenu multimédia "défilement" est une opportunité d'expérience utilisateur qui permet d'ajouter du contexte à la miniature. Texte de remplacement si l'image n'a pas été chargée ou si l'interface utilisateur est lue vocalement s'appuyant sur une technologie d'assistance comme un lecteur d'écran. En savoir plus avec Five Golden règles de texte alternatif texte.

L'attribut loading accepte le mot clé lazy comme moyen de signaler cette image. La source ne doit être récupérée que lorsque l'image se trouve dans la fenêtre d'affichage. Il peut s'agir Cette fonctionnalité est très utile pour les longues listes, car les utilisateurs ne téléchargent des images que pour les éléments jusqu'à ce qu'il s'affiche.

Prendre en charge les préférences de jeu de couleurs de l'utilisateur

Utilisez color-scheme comme balise <meta> pour signaler au navigateur que votre page veut à la fois les styles de user-agent clair et sombre. Mode sombre sans frais ou clair, selon votre affichage:

<meta name="color-scheme" content="dark light">

La balise Meta fournit le signal le plus tôt possible. Ainsi, le navigateur peut sélectionner une couleur de canevas sombre par défaut si l'utilisateur a une préférence de thème sombre ; Cela signifie que la navigation entre les pages du site n'affiche pas de canevas blanc. entre les chargements. Thème sombre parfait entre les chargements vos yeux.

Pour en savoir plus, consultez Thomas Steiner : https://web.dev/color-scheme/.

Ajouter du contenu

Compte tenu de la structure de contenu de ul > li > a > figure > picture > img ci-dessus, la tâche suivante consiste à ajouter des images et des titres à faire défiler. J'ai empaqueté la démo des images et du texte d'espace réservé statiques, mais n'hésitez pas à l'utiliser source de données préférée.

Ajouter un style avec CSS

Il est maintenant temps pour le CSS de transformer cette liste de contenus générique en expérience. Netflix, les plates-formes de téléchargement d'applications et de nombreux autres sites et applications utilisent le format horizontal zones de défilement pour empaqueter la fenêtre d'affichage avec des catégories et des options.

Créer la mise en page de type conteneur de défilement

Il est important d'éviter de couper le contenu dans les mises en page ou de s'appuyer sur du texte avec des points de suspension. De nombreux téléviseurs ont des défileurs multimédias comme celui-ci, mais a trop souvent recours à des points de suspension. Ce n'est pas le cas avec cette mise en page. Elle permet aussi au contenu multimédia de remplacer la taille de colonne, ce qui fait une mise en page suffisamment flexible pour gérer de nombreuses combinaisons intéressantes.

2.
lignes défilantes affichées. L&#39;un n&#39;a pas de points de suspension, ce qui signifie
qu&#39;il est plus grand et chaque
le titre soit entièrement lisible. L&#39;autre est plus court et de 
nombreux titres sont coupés avec
des points de suspension.

Le conteneur permet de remplacer la taille de la colonne en indiquant la taille par défaut une propriété personnalisée. Cette mise en page en grille est avisée sur la taille des colonnes, elle est ne gérant que l'espacement et la direction:

.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 propriété personnalisée est ensuite utilisée par l'élément <picture> pour créer notre format de base: une zone:

.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);
  }
}

Avec seulement quelques styles mineurs, complétez les bases du conteneur de défilement multimédia:

.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);
  }
}

Définir overflow configure <ul> pour permettre le défilement et la navigation au clavier dans sa liste, l'élément ::marker de chaque élément enfant direct <li> est supprimé en obtenant un nouveau type d'affichage inline-block.

Les images ne sont pas encore réactives et explosent immédiatement à l'intérieur. Apprivoisez-les avec quelques tailles, styles et styles de bordures. un dégradé d'arrière-plan en cas de chargement différé:

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%)
    );
}

Marge intérieure du défilement

L'alignement sur le contenu de la page et la surface de défilement bord à bord sont essentielle à un composant harmonieux et minimal.

Pour obtenir la mise en page de défilement bord à bord qui s’aligne sur notre typographie et les lignes de mise en page, utilisez padding qui correspond à 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 */
}

Correction d'un bug concernant la marge intérieure du défilement horizontal Ce qui précède montre à quel point il devrait être remplir un conteneur de défilement, mais il présente des problèmes de compatibilité en suspens. (corrigé dans Chromium 91 ou version ultérieure). Voir cliquez ici pour en savoir plus. de l'historique, mais la version courte est que la marge intérieure n'a pas toujours été prise en compte dans une vue de défilement.

A
est encadrée en rouge sur l&#39;extrémité intégrée du dernier élément de liste.
la marge intérieure et l&#39;élément ont la même largeur que pour créer l&#39;alignement souhaité.

Pour inciter les navigateurs à placer la marge intérieure à la fin du conteneur de défilement, cibler la dernière figure de chaque liste et ajouter un pseudo-élément qui est le de marge intérieure souhaitée.

.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'utilisation de propriétés logiques permet au conteneur de défilement multimédia de fonctionner dans n'importe quel mode d'écriture. et l'orientation du document.

Alignement sur le défilement

Un conteneur à défilement avec dépassement peut devenir une fenêtre d'affichage ancrée avec une ligne de code CSS. Les enfants doivent ensuite spécifier la manière dont ils souhaitent s'aligner sur cette fenêtre d'affichage.

.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;
  }
}

Mise au point

Ce composant s'inspire de sa popularité considérable sur les téléviseurs, sur les plates-formes de téléchargement d'applications, etc. De nombreuses plateformes de jeux vidéo utilisent un conteneur de défilement multimédia similaire à celui-ci, comme mise en page d'écran d'accueil principal. La concentration est un énorme et pas seulement un petit ajout. Imaginez utiliser ce défileur multimédia de votre canapé avec une télécommande, apportez de petites améliorations à cette interaction:

.horizontal-media-scroller a {
  outline-offset: 12px;

  &:focus {
    outline-offset: 7px;
  }

  @media (prefers-reduced-motion: no-preference) {
    & {
      transition: outline-offset .25s ease;
    }
  }
}

Le style de contour du focus 7px est ainsi éloigné de la zone, ce qui lui donne l'espace de stockage. Si l'utilisateur n'a aucune préférence de mouvement pour réduire le mouvement, le décalage lors d'une transition, ce qui donne un mouvement subtil à l'événement de focus.

Indice de rotation

Les utilisateurs de manettes de jeu et de claviers ont besoin d'une attention particulière dans ces longues listes de le contenu et les options de défilement. Le modèle courant pour résoudre ce problème s'appelle indice mobile. C'est lorsqu'un Le conteneur d'éléments est sélectionné avec le clavier, mais un seul enfant est autorisé à le placer à la fois. Cet élément sélectionnable à la fois est conçu pour permettre de contourner la liste d'éléments potentiellement longue, au lieu d'appuyer sur la touche Tab 50+ fois pour atteindre la fin.

Le premier conteneur de la démo contient 300 éléments. Nous pouvons faire mieux que ils les traversent tous pour atteindre la section suivante.

Pour créer cette expérience, JavaScript doit observer les événements de clavier et sélectionner événements. J'ai créé une petite bibliothèque Open Source npm pour aider à rendre cet utilisateur une expérience utilisateur plus facile à réaliser. Voici comment l'utiliser pour les trois éléments de défilement:

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

Cette démonstration interroge le document à la recherche des éléments de défilement et, pour chacun d'eux, appelle fonction rovingIndex(). Transmettre à rovingIndex() l'élément pour obtenir l'itération du modèle, comme un conteneur de liste et un sélecteur de requête cible, au cas où les cibles de ciblage ne sont pas des descendants directs.

document.querySelectorAll('.horizontal-media-scroller')
  .forEach(scroller =>
    rovingIndex({
      element: scroller,
      target: 'a',
}))

Pour en savoir plus sur cet effet, consultez la bibliothèque Open Source roving-ux.

Format

Au moment de la rédaction de ce post, la compatibilité aspect-ratio est derrière un dans Firefox, mais disponible dans les navigateurs Chromium ou les boîtiers décodeurs. Depuis le la mise en page de la grille de défilement des éléments multimédias spécifie uniquement la direction et l'espacement, modification dans une requête média de la fonctionnalité qui vérifie si les proportions sont acceptées. Amélioration progressive avec des défilements multimédias plus dynamiques.

A
un cadre au format 4:4 est affiché à côté des autres formats utilisés (16:9)
et 4:3

@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);
      }
    }
  }
}

Si le navigateur accepte la syntaxe aspect-ratio, les images du conteneur de défilement multimédia sont mise à niveau vers la taille aspect-ratio. En utilisant la syntaxe d'imbrication de brouillon, chaque image modifie son format selon qu'il s'agit de la première, de la deuxième ou de la troisième ligne. La la syntaxe Nest permet également de définir de petites les ajustements de la fenêtre d'affichage, juste là, avec l'autre logique de dimensionnement.

Avec ce CSS, comme la fonctionnalité est disponible dans un plus grand nombre de moteurs de navigation, il est facile de une mise en page plus visuellement attrayante.

Préfère les données réduites

Bien que la technique suivante ne soit disponible derrière un indicateur dans Canary Je voulais vous expliquer comment je pourrais gagner un temps considérable en termes de temps de chargement des pages et l'utilisation des données avec quelques lignes de CSS. La requête média prefers-reduced-data de level 5 permet de demander si l'appareil est en tout état de données réduit, comme un mode Économiseur de données. Si c'est le cas, je peux modifier document, et dans ce cas, masquer les images.

ALT_TEXT_HERE

figure {
  @media (prefers-reduced-data: reduce) {
    & {
      min-inline-size: var(--size);

      & > picture {
        display: none;
      }
    }
  }
}

Il est toujours possible de naviguer dans le contenu, sans que les images volumineuses soient trop lourdes. téléchargée. Voici le site avant d'ajouter le CSS prefers-reduced-data:

(7 requêtes, 100 Ko de ressources en 131 ms)

ALT_TEXT_HERE

Voici les performances du site après l'ajout du CSS prefers-reduced-data:

ALT_TEXT_HERE

(71 requêtes, 1,2 Mo de ressources en 1,07 s)

64 requêtes de moins, soit environ 60 images dans la fenêtre d'affichage (tests effectués sur un grand écran) de cet onglet du navigateur, le chargement de la page a augmenté d'environ 80 % et 10% des données sur le fil. Le CSS est plutôt efficace.

Conclusion

Maintenant que tu sais comment j'ai fait, comment faire ?! 🙂

Diversifiez nos approches et découvrons toutes les manières de créer des applications sur le Web. Créez un Codepen ou hébergez votre propre démo, envoyez-moi un tweet pour que je l'ajoute au section "Remix de la communauté" ci-dessous.

Source

Remix de la communauté

Rien à afficher pour le moment !