Défilement bien contrôlé avec CSS Scroll Snap

Créez des expériences de défilement bien contrôlées en déclarant des positions d'ancrage.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

La fonctionnalité d'ancrage de défilement CSS permet aux développeurs Web de créer des expériences de défilement bien contrôlées en déclarant des positions d'ancrage. Les articles paginés et les carrousels d'images en sont deux exemples couramment utilisés. CSS Scroll Snap fournit une API cohérente et facile à utiliser pour créer ces modèles d'expérience utilisateur populaires.

Contexte

Avantages de l'ancrage du défilement

Le défilement est un moyen populaire et naturel d'interagir avec le contenu sur le Web. C'est le moyen natif de la plate-forme de fournir un accès à plus d'informations que ce qui n'est visible à l'écran en une seule fois, ce qui est particulièrement important sur les plates-formes mobiles avec une surface d'écran limitée. Il n'est donc pas surprenant que les auteurs Web préfèrent de plus en plus organiser le contenu en listes plates déroulantes par opposition à des hiérarchies profondes.

Le principal inconvénient du défilement est son manque de précision. Il est rare qu'un défilement soit aligné sur un paragraphe ou une phrase. Ceci est encore plus prononcé pour les contenus paginés ou détaillés avec des limites significatives lorsque le défilement se termine au milieu de la page ou de l'image, le laissant partiellement visible. Ces cas d'utilisation bénéficient d'une expérience de défilement bien contrôlée.

Les développeurs Web s'appuient depuis longtemps sur des solutions JavaScript pour contrôler le défilement afin de remédier à cette insuffisance. Toutefois, les solutions basées sur JavaScript ne sont pas en mesure de fournir une solution ultraprécise en raison de l'absence de primitives de personnalisation du défilement ou de l'accès au défilement composite. L'ancrage de défilement CSS est une solution rapide, haute fidélité et facile à utiliser qui fonctionne de manière cohérente sur tous les navigateurs.

L'ancrage de défilement CSS permet aux auteurs Web de marquer chaque conteneur de défilement avec des limites pour terminer les opérations de défilement. Les navigateurs choisissent ensuite la position de fin la plus appropriée en fonction des spécificités de l'opération de défilement, de la mise en page et de la visibilité du conteneur de défilement, ainsi que des détails des positions d'ancrage, puis exécutent une animation fluide à cet endroit. Pour en revenir à notre exemple précédent, lorsque l'utilisateur termine de faire défiler le carrousel, son image visible se met en place. Aucun ajustement de défilement n'est nécessaire par JavaScript.

Exemple d'utilisation de l'ancrage de défilement CSS avec un carrousel d'images
Exemple d'utilisation de l'ancrage de défilement CSS avec un carrousel d'images. Ici, l'ancrage du défilement garantit qu'à la fin du défilement, le centre horizontal de l'image est aligné sur le centre horizontal du conteneur de défilement.

Aligner sur le défilement CSS

L'ancrage de défilement consiste à ajuster le décalage de défilement d'un conteneur de défilement pour qu'il se trouve à la position d'ancrage souhaitée une fois l'opération de défilement terminée.

Vous pouvez activer l'ancrage du défilement pour un conteneur de défilement à l'aide de la propriété scroll-snap-type. Cela indique au navigateur qu'il doit envisager d'ancrer ce conteneur de défilement aux positions d'ancrage produites par ses descendants. scroll-snap-type détermine l'axe sur lequel le défilement se produit (x, y ou both), et la sévérité d'ancrage : mandatory, proximity. Nous y reviendrons plus tard.

Une position d'ancrage peut être obtenue en déclarant un alignement souhaité sur un élément. Cette position correspond au décalage de défilement auquel le conteneur de défilement ancêtre le plus proche et l'élément sont alignés comme spécifié pour l'axe donné. Les alignements suivants sont possibles sur chaque axe: start, end, center.

Un alignement start signifie que le bord de début du Snapchat du conteneur de défilement doit être aligné avec le bord de début de la zone d'ancrage de l'élément. De même, les alignements end et center signifient que le bord ou le centre de l'ancrage du conteneur de défilement doit être aligné avec le bord ou le centre de la zone d'ancrage de l'élément.

Exemple d'alignements sur un axe de défilement horizontal.

Les exemples suivants illustrent comment utiliser ces concepts.

Un cas d'utilisation courant de l'ancrage du défilement est le carrousel d'images. Par exemple, pour créer un carrousel d'images horizontal qui s'ancre sur chaque image lorsque vous faites défiler l'écran, nous pouvons spécifier que le conteneur de défilement affiche un élément scroll-snap-type obligatoire sur l'axe horizontal. Définissez chaque image sur scroll-snap-align: center pour que l'ancrage centre l'image dans le carrousel.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

Étant donné que les positions d'ancrage sont associées à un élément, l'algorithme d'ancrage peut déterminer quand et comment il effectue l'ancrage en fonction de l'élément et de la taille du conteneur de défilement. Prenons l'exemple du cas où une image est plus grande que le carrousel. Un algorithme d'ancrage naïf peut empêcher l'utilisateur de faire un panoramique pour voir l'image complète. Cependant, la spécification exige que les implémentations détectent ce cas et permettent à l'utilisateur de faire défiler l'image librement au sein de l'image, en ne s'en arrêtant qu'aux bords de l'image.

Voir la démonstration | Source

Exemple: Une page de produit ayant fait l'objet d'un parcours

Un autre cas courant d'ancrage du défilement peut être bénéfique : les pages comportant plusieurs sections logiques pour faire défiler verticalement une page de produit standard, par exemple. scroll-snap-type: y proximity; convient plus naturellement à ce genre de cas. Elle n'interfère pas lorsque l'utilisateur fait défiler une section particulière en faisant défiler la page, mais s'accroche et attire l'attention sur une nouvelle section lorsqu'il fait défiler l'écran suffisamment près.

Voici comment procéder:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

Marge intérieure et marge de défilement

La page des produits a un en-tête supérieur fixe. Le concepteur a également demandé qu'une partie de la section supérieure reste visible lorsque le conteneur de défilement est ancré, afin de fournir aux utilisateurs un indice de conception sur le contenu ci-dessus.

La propriété scroll-padding est une nouvelle propriété CSS qui permet d'ajuster la région visible effective du conteneur de défilement (ou Snapchat), qui est utilisée pour calculer les alignements d'ancrage de défilement. La propriété définit un encart dans la zone de marge intérieure du conteneur de défilement. Dans notre exemple, un encart supplémentaire 15vh a été ajouté en haut, ce qui indique au navigateur de considérer une position inférieure, 15vh sous le bord supérieur du conteneur de défilement, comme bord de début vertical pour l'ancrage du défilement. Lors de l'ancrage, le bord de début de l'élément cible de l'ancrage est vidé par cette nouvelle position, ce qui laisse de l'espace au-dessus.

La propriété scroll-margin définit le décalage utilisé pour ajuster la zone d'effet de la cible d'ancrage de la même manière que scroll-padding fonctionne sur le conteneur de défilement d'un Snap.

Vous avez peut-être remarqué que ces deux propriétés ne contiennent pas le mot "snap". Cette action est intentionnelle, car elle modifie la case pour toutes les opérations de défilement pertinentes et ne se limite pas à l'ancrage du défilement. Par exemple, Chrome les prend en compte lors du calcul de la taille de la page pour les opérations de défilement de pagination telles que PageDown et PageUp, ainsi que lors du calcul de la durée de défilement pour l'opération Element.scrollIntoView().

Voir la démonstration | Source

Interaction avec d'autres API de défilement

API DOM Scrolling

L'ancrage de défilement se produit après toutes les opérations de défilement, y compris celles déclenchées par le script. Lorsque vous utilisez des API telles que Element.scrollTo, le navigateur calcule la position de défilement prévue pour l'opération, puis applique la logique d'ancrage appropriée pour trouver l'emplacement final ancré. Ainsi, le script utilisateur n'a pas besoin d'effectuer de calculs manuels pour l'ancrage.

Défilement fluide

Le défilement fluide contrôle le comportement d'une opération de défilement programmatique, tandis que l'ancrage de défilement détermine sa destination. Étant donné qu'ils contrôlent les aspects orthogonaux du défilement, ils peuvent être utilisés ensemble et se complètent.

Comportement du défilement hors limites

L'API de comportement de défilement hors limites contrôle la façon dont le défilement est enchaîné sur plusieurs éléments. Elle n'est pas affectée par l'ancrage du défilement.

Mises en garde et bonnes pratiques

Évitez d'utiliser l'ancrage obligatoire lorsque les éléments cibles sont très espacés. Par conséquent, le contenu situé entre les positions d'ancrage peut devenir inaccessible.

Dans de nombreux cas, l'ancrage de défilement peut être ajouté en tant qu'amélioration sans avoir à détecter de fonctionnalités. Si nécessaire, utilisez @supports ou CSS.supports pour détecter la compatibilité avec l'ancrage de défilement CSS. Évitez d'utiliser scroll-snap-type, qui est également présent dans la spécification obsolète.

Détection de caractéristiques dans CSS

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

Détection de caractéristiques en JavaScript

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

Ne partez pas du principe que les API de défilement programmatique telles que Element.scrollTo se terminent toujours au décalage de défilement demandé. L'ancrage de défilement peut ajuster le décalage de défilement une fois le défilement programmatique terminé. Notez que ce n'était pas une bonne hypothèse avant même l'ancrage du défilement, car celui-ci pouvait avoir été interrompu pour d'autres raisons, mais c'est particulièrement le cas avec l'ancrage du défilement.

Travaux futurs

L'expérience de défilement a fait l'objet d'une enquête récente menée par l'équipe Chrome. Les résultats de l'enquête ont identifié plusieurs domaines qui nécessitent des efforts supplémentaires pour réduire l'écart entre les bibliothèques de plug-ins et les CSS. Les devoirs à venir porteront sur scroll-snap, y compris:

  1. Disponibilité et compatibilité des API avec différents navigateurs
  2. Travaillez sur de nouvelles API CSS telles que scroll-start.
  3. Travaillez sur les nouveaux événements JS tels que snapChanged().