Utiliser les requêtes d'état de défilement des conteneurs
Les requêtes d'état de défilement des conteneurs (container scroll-state queries en anglais) constituent un type de requête de conteneur. Plutôt que d'appliquer de manière sélective des styles aux éléments descendants en fonction de la taille du conteneur, les requêtes d'état de défilement vous permettent d'appliquer de manière sélective des styles aux éléments descendants en fonction de l'état de défilement du conteneur. Cela peut notamment concerner le fait que le conteneur soit partiellement défilé, aligné sur un ancêtre de type conteneur d'alignement de défilement, ou positionné à l'aide de position: sticky et collé à une limite d'un ancêtre de conteneur de défilement.
Cet article explique comment utiliser les requêtes d'état de défilement des conteneurs, en passant en revue un exemple de chaque type. Il suppose que vous connaissez les bases des requêtes de conteneur. Si vous êtes nouveau dans les requêtes de conteneur, lisez les requêtes de conteneur CSS avant de continuer.
Types de requêtes d'état de défilement des conteneurs
Il existe trois descripteurs @container que vous pouvez utiliser dans une requête scroll-state() :
scrollable: Interroge si un conteneur peut être défilé dans la direction donnée avec un défilement initié par l'utilisateur·ice (par exemple en faisant glisser la barre de défilement ou en utilisant un geste sur le pavé tactile). En d'autres termes, y a-t-il du contenu débordant dans la direction donnée qui peut être défilé ? C'est utile pour appliquer des styles liés à la position de défilement d'un conteneur de défilement. Par exemple, vous pouvez afficher un indice encourageant les utilisateur·ice·s à faire défiler vers le bas pour voir plus de contenu lorsque la barre de défilement est en haut, et le masquer lorsque l'utilisateur·ice a effectivement commencé à faire défiler.scrolled: Interroge si un conteneur a été récemment défilé dans la direction donnée. Cela vous permet d'appliquer sélectivement des styles en fonction de la direction de défilement de l'utilisateur·ice, par exemple une barre de menu supérieure qui ne s'affiche que lorsque l'utilisateur·ice fait défiler vers le haut.snapped: Interroge si un conteneur va être aligné sur un ancêtre de type accrochage au défilement le long d'un axe donné. C'est utile pour appliquer des styles lorsqu'un élément est aligné sur un conteneur de type accrochage au défilement. Par exemple, vous pouvez mettre en évidence un élément aligné d'une certaine manière, ou révéler une partie de son contenu qui était précédemment cachée.stuck: Interroge si un conteneur avec une valeur depositiondestickyest collé à un bord de son ancêtre de conteneur de défilement. C'est utile pour mettre en forme différemment les élémentsposition: stickylorsqu'ils sont collés — par exemple, vous pouvez leur donner un schéma de couleurs ou une mise en page différente.
Aperçu de la syntaxe
Pour établir un élément conteneur comme conteneur de requête d'état de défilement, définissez la propriété container-type avec une valeur de scroll-state. Vous pouvez également lui donner un nom avec container-name, afin de pouvoir le cibler avec une requête de conteneur spécifique :
.container {
container-type: scroll-state;
container-name: mon-conteneur;
}
Vous pouvez ensuite créer un bloc @container qui définit la requête, les règles qui sont appliquées aux enfants du conteneur si le test réussit, et éventuellement, le container-name du ou des conteneurs que vous souhaitez interroger. Si vous ne définissez pas de container-name, la requête de conteneur est appliquée à tous les conteneurs de requête d'état de défilement de la page.
Ici, nous interrogeons uniquement les conteneurs nommés mon-conteneur pour déterminer si le conteneur peut être défilé vers son bord supérieur :
@container mon-conteneur scroll-state(scrollable: top) {
/* Les règles CSS vont ici */
}
Note :
Pour séparer les requêtes d'état de défilement des autres requêtes de conteneur, les descripteurs et valeurs d'état de défilement sont placés entre parenthèses, précédés de scroll-state (scroll-state( ... )). Ces constructions ressemblent à des fonctions, mais elles ne le sont pas.
Utiliser les requêtes scrollable
Les requêtes d'état de défilement scrollable, écrites sous la forme scroll-state(scrollable: <mot-clé>), testent si l'ancêtre défilable d'un conteneur peut être défilé dans la direction donnée avec un défilement initié par l'utilisateur·ice. Sinon, la requête retourne false.
La valeur du mot-clé indique la direction pour laquelle vous testez la disponibilité du défilement, par exemple :
top: teste si le conteneur peut être défilé vers son bord supérieur.inline-end: teste si le conteneur peut être défilé vers son bord de fin en ligne.y: teste si le conteneur peut être défilé dans une ou les deux directions le long de son axe vertical.
Si le test réussit, les règles à l'intérieur du bloc @container sont appliquées aux descendants du conteneur de défilement correspondant.
Examinons un exemple dans lequel nous avons un conteneur défilant rempli de contenu, et un petit lien pratique pour revenir en haut si souhaité. Nous utilisons une requête scrollable pour n'afficher le lien que lorsque l'utilisateur·ice a commencé·e à faire défiler le contenu vers le bas.
HTML
Dans le HTML, nous avons un élément <article> contenant suffisamment de contenu pour provoquer le défilement du document, précédé d'un lien de retour en haut :
<a class="retour-en-haut" href="#" aria-label="Haut de page">↑</a>
<article>
<h1>
Lecteur avec lien de « retour en haut » contrôlé par une requête
de conteneur
</h1>
<section>
<header>
<h2>Cette première section est intéressante</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</header>
...
</section>
...
</article>
Nous avons masqué la plupart du HTML pour plus de concision.
CSS
Le lien .retour-en-haut reçoit une valeur de position à fixed, placé dans le coin inférieur droit de la fenêtre, et déplacé hors de la fenêtre à l'aide d'une valeur translate de 80px 0. Une valeur de transition anime le translate et la background-color lorsque l'une ou l'autre de ces valeurs change.
.retour-en-haut {
width: 64px;
height: 64px;
color: white;
text-align: center;
position: fixed;
bottom: 10px;
right: 10px;
translate: 80px 0;
transition:
0.4s translate,
0.2s background-color;
}
Le conteneur de défilement dans cet exemple est l'élément <html> lui-même, désigné comme un conteneur de requête d'état de défilement avec une valeur de container-type sur scroll-state. Le nom de conteneur (container-name) n'est pas strictement nécessaire mais est utile dans les cas où le code est ajouté à une base de code avec plusieurs conteneurs de requête d'état de défilement ciblés par différentes requêtes.
html {
container-type: scroll-state;
container-name: scroller;
}
Ensuite, nous définissons un bloc @container qui définit le nom du conteneur ciblé par cette requête, ainsi que la requête elle-même — scrollable: top. Cette requête applique les règles contenues dans le bloc uniquement si l'élément <html> peut être défilé vers son bord supérieur — en d'autres termes, si le conteneur a été précédemment défilé vers le bas. Dans ce cas, translate: 0 0 est appliqué au lien .retour-en-haut, ce qui le fait revenir à l'écran.
@container scroller scroll-state(scrollable: top) {
.retour-en-haut {
translate: 0 0;
}
}
N'avons caché le reste du CSS de l'exemple pour des raisons de concision.
Résultat
Essayez de faire défiler le document vers le bas et notez comment le lien « retour-en-haut » apparaît en conséquence, animant en douceur depuis le côté droit de la fenêtre grâce à la transition. Si vous faites défiler vers le haut en activant le lien ou en faisant défiler manuellement, le lien « retour-en-haut » disparaît de l'écran.
Utiliser les requêtes scrolled
Les requêtes d'état de défilement scrolled, écrites sous la forme scroll-state(scrolled: <keyword>), testent si l'ancêtre défilant d'un conteneur a été récemment défilé dans la direction donnée. Sinon, la requête retourne false.
La valeur du mot-clé indique la direction que vous testez. Par exemple :
block-start: Teste si le conteneur a été récemment défilé vers son bord de début de bloc.right: Teste si le conteneur a été récemment défilé vers son bord droit.y: Teste si le conteneur a été récemment défilé vers le haut ou vers le bas le long de l'axe y.none: Teste si le conteneur n'est pas un conteneur de défilement ou n'a pas été défilé dans une direction depuis le rendu.
Si le test retourne true, les règles à l'intérieur du bloc @container sont appliquées aux descendants du conteneur de défilement correspondant.
Voyons un exemple de conteneur de défilement avec une requête scrolled qui affiche les « barres » de contenu en haut et en bas uniquement lorsque l'utilisateur·ice fait défiler vers le haut ou vers le bas, respectivement.
HTML
Dans notre HTML, nous avons un élément <article> contenant suffisamment de contenu pour provoquer le défilement du document, précédé de deux éléments <div> qui représentent nos « barres » supérieure et inférieure :
<div class="barre" id="barre-haute">
Vous faites actuellement défiler vers le haut.
</div>
<div class="barre" id="barre-basse">
Vous faites actuellement défiler vers le bas.
</div>
<article>
<h1>Document avec une requête de conteneur défilé</h1>
<section>
<header>
<h2>Cette première section est intéressante</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</header>
...
</section>
...
</article>
Nous avons masqué la plupart du HTML pour des raisons de concision.
CSS
Les « barres » reçoivent un style rudimentaire. Plus important encore, elles reçoivent une valeur position de fixed, que nous décalons de chaque côté en utilisant les valeurs left et right.
.barre {
border-radius: 10px;
border: 1px solid black;
background-color: #00000099;
padding: 10px;
color: white;
text-shadow: 1px 1px 1px black;
display: flex;
justify-content: center;
align-items: center;
position: fixed;
left: 5px;
right: 5px;
}
Ensuite, nous définissons des valeurs de longueur négatives pour top et bottom sur les barres supérieure et inférieure afin qu'elles soient cachées au-dessus et en dessous de la fenêtre par défaut. Nous ajoutons une transition pour les animer en douceur lorsqu'elles apparaissent à l'écran lorsque leurs valeurs translate changent.
#barre-haute {
top: -50px;
transition: 0.6s translate;
}
#barre-basse {
bottom: -50px;
transition: 0.6s translate;
}
Le conteneur de défilement dans cet exemple est l'élément <html> lui-même, désigné comme un conteneur de requêtes d'état de défilement avec une valeur de container-type à scroll-state. Le nom de conteneur (container-name) n'est pas strictement nécessaire, mais il est utile lorsqu'une base de code comporte plusieurs conteneurs de requêtes d'état de défilement ciblés par différentes requêtes.
html {
container-type: scroll-state;
container-name: defileur;
}
Ensuite, nous définissons deux blocs @container, tous deux ciblant le nom de conteneur defileur. Le premier bloc définit une requête scrolled: block-end et le second définit une requête scrolled: block-start. Respectivement, ces requêtes appliquent les règles contenues dans leur bloc uniquement si l'élément <html> a été récemment défilé vers son bord de fin de bloc ou de début de bloc. En d'autres termes, lorsque le conteneur est défilé vers le bas ou vers le haut. Lorsque l'une de ces conditions devient vraie, la barre référencée à l'intérieur du bloc a une valeur translate définie pour la faire apparaître à l'écran. La barre référencée dans la @condition qui n'est plus vraie disparaît de l'écran.
@container defileur scroll-state(scrolled: block-start) {
#barre-haute {
translate: 0 55px;
}
}
@container defileur scroll-state(scrolled: block-end) {
#barre-basse {
translate: 0 -55px;
}
}
Nous avons masqué le reste du CSS de l'exemple pour plus de concision.
Résultat
Essayez de faire défiler le document vers le haut et vers le bas, et notez comment les différentes barres apparaissent en conséquence, animant en douceur à l'écran et hors de l'écran.
Utiliser les requêtes snapped
Pertinent uniquement lorsque le défilement avec accrochage est implémenté, les requêtes scroll-state snapped, écrites comme scroll-state(snapped: <keyword>), testent si un conteneur va être aligné sur un ancêtre du conteneur de défilement avec accrochage le long de l'axe donné. Sinon, la requête retourne false.
La valeur du mot-clé dans ce cas indique la direction dans laquelle vous testez la capacité de l'élément à s'accrocher, par exemple :
x: Testez si le conteneur s'accroche horizontalement à son ancêtre conteneur de défilement avec accrochage.inline: Testez si le conteneur s'accroche à son ancêtre conteneur de défilement avec accrochage dans la direction inline.y: Testez si le conteneur s'accroche à son ancêtre conteneur de défilement avec accrochage dans les deux directions.
Pour évaluer un conteneur avec une requête d'état de défilement snapped autre que none, il doit s'agir d'un conteneur ayant un ancêtre conteneur de défilement avec accrochage, c'est-à-dire que l'ancêtre a une valeur scroll-snap-type autre que none. La requête de conteneur scroll-state(snapped: none) correspond aux conteneurs d'état de défilement qui n'ont pas de conteneur de défilement comme ancêtre.
L'évaluation se produit lorsque l'évènement scrollsnapchanging se déclenche sur le conteneur de défilement avec accrochage.
Si le test réussit, les règles à l'intérieur du bloc @container sont appliquées aux descendants du conteneur cible de défilement avec accrochage correspondant.
Dans cet exemple, nous examinons un conteneur de défilement avec accrochage dont les enfants s'accrochent verticalement et utilisons une requête snapped pour mettre en forme les enfants uniquement lorsqu'ils sont accrochés ou sur le point de l'être.
HTML
Le code HTML se compose d'un élément <main> qui agit comme conteneur d'accrochage au défilement. À l'intérieur se trouvent plusieurs éléments <section> qui servent de cibles d'accrochage. Chaque <section> contient un élément d'encapsulation <div> et un titre <h2>. Les éléments d'encapsulation sont inclus pour créer une cible de style, car les requêtes de conteneur permettent de mettre en forme les descendants d'un conteneur, et non le conteneur lui-même.
<main>
<section>
<div class="enveloppe">
<h2>Section 1</h2>
</div>
</section>
...
</main>
Nous avons masqué la majeure partie du HTML pour des raisons de concision.
CSS
Nous avons défini une valeur de débordement (overflow) sur scroll et une hauteur (height) fixe sur l'élément <main> pour en faire un conteneur de défilement vertical. Nous avons également défini une valeur scroll-snap-type à y mandatory pour transformer <main> en conteneur de défilement auquel les cibles de défilement s'alignent le long de l'axe vertical ; mandatory signifie qu'une cible de défilement est toujours alignée.
main {
overflow: scroll;
scroll-snap-type: y mandatory;
height: 450px;
width: 250px;
border: 3px solid black;
}
Les éléments <section> sont désignés comme cibles de défilement en définissant une valeur scroll-snap-align qui n'est pas none. La valeur center signifie qu'ils s'alignent au centre de leur conteneur.
section {
font-family: "Helvetica", "Arial", sans-serif;
width: 150px;
height: 150px;
margin: 50px auto;
scroll-snap-align: center;
}
Nous voulons permettre aux éléments <section> d'être interrogés. Plus précisément, nous voulons tester si les éléments <section> sont en train de s'aligner sur leur conteneur, nous les désignons donc comme des conteneurs de requêtes d'état de défilement en définissant une valeur container-type de scroll-state sur eux. Nous leur donnons également un container-name, ce qui n'est pas strictement nécessaire, mais est utile si notre code devient plus complexe plus tard et que nous avons plusieurs conteneurs de requêtes d'état de défilement que nous voulons cibler avec différentes requêtes.
section {
container-type: scroll-state;
container-name: conteneur-accroche;
}
Ensuite, nous définissons un bloc @container qui définit le nom du conteneur que nous ciblons avec cette requête, ainsi que la requête elle-même — snapped: y. Cette requête applique les règles contenues dans le bloc uniquement si un élément <section> est en train de s'aligner verticalement sur son conteneur. Dans ce cas, nous appliquons un nouveau background et color à l'élément enfant .enveloppe de <section> pour le mettre en évidence.
@container conteneur-accroche scroll-state(snapped: y) {
.enveloppe {
background: purple;
color: white;
}
}
Résultat
Le résultat rendu est montré ci-dessous. Essayez de faire défiler le conteneur vers le haut et vers le bas, et notez comment le style de <section> change lorsqu'il s'aligne sur son conteneur.
Utiliser les requêtes stuck
La requête d'état de défilement stuck teste si un conteneur avec une valeur position de sticky est collé à un bord de son conteneur de défilement ancêtre. Sinon, la requête retourne false.
La valeur du mot-clé dans ce cas indique le bord du conteneur de défilement que vous testez, par exemple :
top: Teste si le conteneur est collé au bord supérieur de son conteneur de défilement ancêtre.block-end: Teste si le conteneur est collé au bord inférieur de son conteneur de défilement ancêtre.none: Teste si le conteneur n'est collé à aucun bord de son conteneur de défilement ancêtre. Notez que les requêtesnonecorrespondent même si le conteneur n'a pasposition: stickydéfini.
Si la requête retourne true, les règles à l'intérieur du bloc @container sont appliquées aux descendants du conteneur position: sticky correspondant.
Voyons un exemple où nous avons un conteneur défilant avec un contenu débordant, dans lequel les en-têtes sont définis avec position: sticky et restent collés au bord supérieur du conteneur lorsqu'ils défilent jusqu'à cette position. Nous utilisons une requête d'état de défilement stuck pour mettre en forme les en-têtes différemment lorsqu'ils sont collés au bord supérieur.
HTML
Dans le HTML, nous avons un élément <article> contenant suffisamment de contenu pour provoquer le défilement du document. Il est structuré en plusieurs éléments <section>, chacun contenant un <header> avec du contenu imbriqué :
<article>
<h1>
Lecteur collant avec requête de conteneur en fonction de l'état de
défilement
</h1>
<section>
<header>
<h2>Cette première section est intéressante</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</header>
...
</section>
<section>
<header>
<h2>Cette section, pas tellement</h2>
<p>Confecta res esset.</p>
</header>
...
</section>
...
</article>
Nous avons caché la majeure partie du HTML pour des raisons de concision.
CSS
Chaque <header> a une valeur de position à sticky et une valeur de top à 0, ce qui les fixe au bord supérieur du conteneur de défilement. Pour tester si les éléments <header> sont fixés au bord supérieur du conteneur, ils sont désignés comme des conteneurs de requêtes d'état de défilement avec une valeur container-type de scroll-state. Le container-name n'est pas strictement nécessaire mais est utile si ce code est ajouté à une base de code avec plusieurs conteneurs de requêtes d'état de défilement ciblés par différentes requêtes.
header {
background: white;
position: sticky;
top: 0;
container-type: scroll-state;
container-name: titre-collant;
}
Nous donnons également aux éléments <h2> et <p> à l'intérieur des éléments <header> une mise en forme de base, ainsi qu'une valeur transition afin qu'ils s'animent en douceur lorsque leurs valeurs background changent.
h2,
header p {
margin: 0;
transition: 0.4s background;
}
h2 {
padding: 20px 5px;
margin-bottom: 10px;
}
header p {
font-style: italic;
padding: 10px 5px;
}
Ensuite, nous définissons un bloc @container qui définit le nom du conteneur que nous ciblons avec cette requête, ainsi que la requête elle-même — stuck: top. Cette requête applique les règles contenues dans le bloc uniquement si un élément <header> est fixé au bord supérieur de son conteneur de défilement. Dans ce cas, un background différent et une box-shadow sont appliqués aux éléments <h2> et <p> contenus.
@container titre-collant scroll-state(stuck: top) {
h2,
p {
background: #cccccc;
box-shadow: 0 5px 2px #00000077;
}
}
Nous avons masqué le reste du CSS pour plus de concision.
Résultat
Essayez de faire défiler le document vers le bas et vers le haut, et notez comment les éléments <h2> et <p> passent à un nouveau schéma de couleurs lorsqu'ils deviennent collés au bord supérieur de leur conteneur.
Voir aussi
- La propriété
container-name - La propriété
container-type - La propriété
position - La règle
@container - Requêtes de conteneur CSS
- Utiliser les requêtes de taille et de style de conteneur
- Le module des règles conditionnelles CSS
- Le module du positionnement CSS