Créez des expériences de défilement bien contrôlées en déclarant des positions de défilement scroll-snap.
La fonctionnalité CSS Scroll Snap permet aux développeurs Web de créer des expériences de défilement bien contrôlées en déclarant des positions de défilement scroll-snap. Les articles paginés et les carrousels d'images en sont deux exemples courants. Le défilement scroll-snap CSS fournit une API facile à utiliser et cohérente pour créer ces modèles d'expérience utilisateur populaires.
Arrière-plan
Pourquoi utiliser le défilement scroll-snap ?
Le défilement est un moyen populaire et naturel d'interagir avec le contenu sur le Web. Il s'agit du moyen natif de la plate-forme pour fournir l'accès à plus d'informations que ce qui est visible à l'écran en même temps, ce qui est particulièrement important sur les plates-formes mobiles avec un espace d'écran limité. 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 plutôt qu'en hiérarchies profondes.
Le principal inconvénient du défilement est son manque de précision. Il est rare qu'un défilement s'arrête exactement au niveau d'un paragraphe ou d'une phrase. Cela 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, la 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 basées sur JavaScript pour contrôler le défilement afin de remédier à ce problème. Cependant, les solutions basées sur JavaScript ne fournissent pas une solution de fidélité complète en raison de l'absence de primitives de personnalisation du défilement ou d'accès au défilement composite. Le défilement scroll-snap CSS est une solution rapide, haute fidélité et facile à utiliser qui fonctionne de manière cohérente sur tous les navigateurs.
Le défilement scroll-snap CSS permet aux auteurs Web de marquer chaque conteneur de défilement avec des limites pour les opérations de défilement à terminer. Les navigateurs choisissent ensuite la position finale la plus appropriée en fonction des particularité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'alignement, puis l'animent de manière fluide. Pour en revenir à notre exemple précédent, lorsque l'utilisateur finit de faire défiler le carrousel, l'image visible s'aligne. Aucun ajustement du défilement n'est nécessaire par JavaScript.
Défilement scroll-snap CSS
Le défilement scroll-snap consiste à ajuster le décalage de défilement d'un conteneur de défilement pour qu'il se trouve à une position d'alignement préférée une fois l'opération de défilement terminée.
Un conteneur de défilement peut être activé pour le défilement scroll-snap à l'aide de la propriété scroll-snap-type. Cela indique au navigateur qu'il doit envisager d'aligner ce conteneur de défilement sur les positions d'alignement produites par ses descendants. scroll-snap-type détermine l'axe sur lequel le défilement se produit : x, y ou both, ainsi que la rigueur de l'alignement : mandatory, proximity. Nous y reviendrons plus tard.
Une position d'alignement peut être produite en déclarant l'alignement souhaité sur un élément.
Cette position correspond au décalage de défilement auquel le conteneur de défilement qui est l'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épart du point d'ancrage du conteneur de défilement doit être aligné sur le bord de départ 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 la zone d'ancrage du conteneur de défilement doit être aligné sur le bord ou le centre de la zone d'ancrage de l'élément.
Les exemples suivants illustrent l'utilisation de ces concepts.
Exemple : galerie horizontale
Le défilement scroll-snap est souvent utilisé pour les carrousels d'images. Par exemple, pour créer un carrousel d'images horizontal qui s'aligne sur chaque image lorsque vous faites défiler l'écran, nous pouvons spécifier que le conteneur de défilement doit avoir un scroll-snap-type obligatoire sur l'axe horizontal. Définissez chaque image sur scroll-snap-align: center pour vous assurer que l'alignement 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'alignement sont associées à un élément, l'algorithme d'alignement peut déterminer intelligemment quand et comment aligner l'élément en fonction de sa taille et de celle du conteneur de défilement. Par exemple, imaginez qu'une image soit plus grande que le carrousel. Un algorithme d'ancrage naïf peut empêcher l'utilisateur d'effectuer un panoramique pour voir l'image complète. Toutefois, la spécification exige que les implémentations détectent ce cas et permettent à l'utilisateur de faire défiler librement l'image, en ne l'alignant que sur ses bords.
Exemple : page produit avec parcours d'achat
Les pages comportant plusieurs sections logiques à faire défiler verticalement, par exemple une page produit classique, constituent un autre cas d'utilisation courant qui peut bénéficier du défilement scroll-snap. scroll-snap-type: y proximity; est plus adapté à ce type de cas. Il n'interfère pas lorsqu'un utilisateur fait défiler l'écran jusqu'au milieu d'une section particulière, mais il s'aligne également et attire l'attention sur une nouvelle section lorsqu'il fait défiler l'écran suffisamment près.
Pour cela :
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 produit comporte un en-tête fixe en haut. La conception demandait également 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 visuel sur le contenu situé au-dessus.
La propriété scroll-padding est une nouvelle propriété CSS qui peut être utilisée pour ajuster la zone visible effective du conteneur de défilement, ou snapport, qui est utilisée lors du calcul des alignements de défilement scroll-snap. La propriété définit un encart par rapport à la zone de marge intérieure du conteneur de défilement. Dans notre exemple, un encart supplémentaire de 15vh a été ajouté en haut, ce qui indique au navigateur de considérer une position plus basse, 15vh en dessous du bord supérieur du conteneur de défilement, comme bord de départ vertical pour le défilement scroll-snap. Lors de l'alignement, le bord de début de l'élément cible d'alignement sera aligné sur cette nouvelle position, laissant ainsi de l'espace au-dessus.
La propriété scroll-margin définit la valeur de décalage utilisée pour ajuster la zone effective de la cible d'alignement, de la même manière que scroll-padding fonctionne sur le conteneur de défilement d'alignement.
Vous avez peut-être remarqué que ces deux propriétés ne contiennent pas le mot "snap". C'est intentionnel, car elles modifient en fait la zone pour toutes les opérations de défilement pertinentes et ne se limitent pas au défilement scroll-snap. Par exemple, Chrome les prend en compte lors du calcul de la taille de la page pour les opérations de défilement de page telles que PageDown et PageUp, ainsi que lors du calcul de la quantité de défilement pour l'opération Element.scrollIntoView().
Interaction avec d'autres API de défilement
API de défilement DOM
Le défilement scroll-snap se produit après toutes les opérations de défilement, y compris celles initiées par un script. Lorsque vous utilisez des API telles que Element.scrollTo, le navigateur calcule la position de défilement prévue de l'opération, puis applique la logique d'alignement appropriée pour trouver l'emplacement d'alignement final. Il n'est donc pas nécessaire que le script utilisateur effectue des calculs manuels pour l'alignement.
Défilement fluide
Le défilement fluide contrôle le comportement d'une opération de défilement programmatique, tandis que le défilement scroll-snap détermine sa destination. Comme ils contrôlent des 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 overscroll contrôle la façon dont le défilement est enchaîné sur plusieurs éléments et n'est pas affectée par le défilement scroll-snap.
Remarques et bonnes pratiques
Évitez d'utiliser l'alignement obligatoire lorsque les éléments cibles sont très espacés. Cela peut rendre inaccessible le contenu situé entre les positions d'alignement.
Dans de nombreux cas, le défilement scroll-snap peut être ajouté en tant qu'amélioration sans qu'il soit nécessaire de détecter les fonctionnalités.
Si nécessaire, utilisez @supports ou CSS.supports pour détecter la compatibilité avec le défilement scroll-snap CSS.
Évitez d'utiliser scroll-snap-type, qui est également présent dans la spécification obsolète.
Détection de fonctionnalités en CSS
@supports (scroll-snap-align: start) {
article {
scroll-snap-type: y proximity;
scroll-padding-top: 15vh;
overflow-y: scroll;
}
}
Détection de fonctionnalités 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é. Le défilement scroll-snap peut ajuster le décalage de défilement une fois le défilement programmatique terminé. Notez que cette hypothèse n'était pas correcte, même avant le défilement scroll-snap, car le défilement pouvait être interrompu pour d'autres raisons, mais c'est particulièrement le cas avec le défilement scroll-snap.
Prochains ajouts
L'expérience de défilement a fait l'objet d'une enquête récente de l'équipe Chrome.
Les résultats de l'enquête ont identifié plusieurs domaines nécessitant des efforts supplémentaires pour réduire l'écart entre les bibliothèques de plug-ins et CSS.
Les prochains travaux porteront sur scroll-snap, y compris :
- Disponibilité et compatibilité des API sur les différents navigateurs.
- Travaillez sur de nouvelles API CSS telles que
scroll-start. - Travaillez sur de nouveaux événements JS comme
snapChanged().