Utiliser le flux de lecture CSS pour la navigation séquentielle logique de la sélection

Publié le 1er mai 2025

Les propriétés CSS reading-flow et reading-order sont disponibles à partir de Chrome 137. Cet article explique les raisons de la conception de ces propriétés et fournit quelques détails pour vous aider à les utiliser.

Les méthodes de mise en page telles que les grilles et les flexbox ont transformé le développement du frontend, mais leur flexibilité peut poser problème à certains utilisateurs. Il est très facile de créer une situation dans laquelle l'ordre visuel ne correspond pas à l'ordre source dans l'arborescence DOM. Comme cet ordre de source est celui que le navigateur suit si vous naviguez sur le site à l'aide d'un clavier, certains utilisateurs peuvent rencontrer des sauts inattendus lorsqu'ils naviguent sur une page.

Les propriétés reading-flow et reading-order ont été conçues et ajoutées à la spécification CSS Display pour tenter de résoudre ce problème de longue date.

reading-flow

La propriété CSS reading-flow contrôle l'ordre dans lequel les éléments d'une mise en page flexible, en grille ou en bloc sont exposés aux outils d'accessibilité et la façon dont ils sont sélectionnés à l'aide de méthodes de navigation séquentielles linéaires.

Il accepte une valeur de mot clé, avec une valeur par défaut de normal, qui conserve le comportement de tri des éléments dans l'ordre DOM. Pour l'utiliser dans un conteneur Flex, définissez sa valeur sur flex-visual ou flex-flow. Pour l'utiliser dans un conteneur de grille, définissez sa valeur sur grid-rows, grid-columns ou grid-order.

reading-order

La propriété CSS reading-order vous permet de remplacer manuellement l'ordre des éléments dans un conteneur de flux de lecture. Pour utiliser cette propriété dans un conteneur de grille, flex ou bloc, définissez la valeur reading-flow du conteneur sur source-order et définissez la valeur reading-order de l'élément individuel sur un nombre entier.

Exemple dans Flexbox

Par exemple, vous pouvez avoir un conteneur de mise en page Flex avec trois éléments dans l'ordre inverse des lignes, et vous pouvez également utiliser la propriété "order" pour réorganiser cet ordre.

<div class="box">
 <a href="#">One</a>
 <a href="#">Two</a>
 <a href="#">Three</a>
</div>
.box {
  display: flex;
  flex-direction: row-reverse;
}

.box :nth-child(1) {
  order: 2;
}

Vous pouvez essayer de parcourir ces éléments à l'aide de la touche TAB pour trouver l'élément sélectionnable suivant et des touches TAB+SHIFT pour trouver l'élément sélectionnable précédent. Les éléments sont affichés dans l'ordre source : un, deux, trois.

Du point de vue de l'utilisateur final, cela n'a aucun sens et peut être très déroutant. Il se passe la même chose si nous utilisons un outil de navigation spatiale pour l'accessibilité afin de parcourir la page.

Pour résoudre ce problème, définissez la propriété reading-flow :

.box {
  reading-flow: flex-visual;
}

L'ordre de sélection est désormais : un, trois, deux. C'est la même chose que l'ordre visuel que vous obtiendriez si vous lisiez en anglais de gauche à droite.

Si vous préférez conserver l'ordre de sélection tel qu'il était initialement prévu, dans l'ordre inverse, vous pouvez définir :

.box {
  reading-flow: flex-flow;
}

L'ordre de focus est désormais l'inverse de l'ordre flex : Deux, Trois, Un. Dans les deux cas, la propriété CSS order est prise en compte.

Exemple avec une disposition en grille

Pour voir comment cela fonctionne dans une grille, imaginez que vous créez une mise en page avec des éléments à placement automatique de grille CSS avec douze zones pouvant être sélectionnées.

<div class="wrapper">
 <a href="#">One</a>
 <a href="#">Two</a>
 <a href="#">Three</a>
 <a href="#">Four</a>
 <a href="#">Five</a>
 <a href="#">Six</a>
 <a href="#">Seven</a>
 <a href="#">Eight</a>
 <a href="#">Nine</a>
 <a href="#">Ten</a>
 <a href="#">Eleven</a>
 <a href="#">Twelve</a>
</div>

Vous souhaitez que le cinquième enfant occupe le plus grand espace tout en haut, suivi du deuxième enfant vers le milieu de la grille. Tous les autres enfants peuvent être placés automatiquement dans la grille en suivant un modèle de colonne.

.wrapper {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 100px;
}
.wrapper a:nth-child(2) {
  grid-column: 3;
  grid-row: 2 / 4;
}
.wrapper a:nth-child(5) {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}

Essayez de parcourir ces éléments à l'aide de la touche TAB pour trouver l'élément sélectionnable suivant et des touches TAB+SHIFT pour trouver l'élément sélectionnable précédent. Les éléments sont classés dans l'ordre source : de un à douze.

Pour résoudre ce problème, définissez la propriété reading-flow :

.wrapper {
  reading-flow: grid-rows;
}

L'ordre de sélection est désormais le suivant : cinq, un, trois, deux, quatre, six, sept, huit, neuf, dix, onze, douze. Il suit l'ordre visuel, ligne par ligne.

Si vous souhaitez que l'ordre de lecture suive l'ordre des colonnes, vous pouvez utiliser la valeur de mot clé grid-columns. L'ordre de focus devient alors : cinq, six, neuf, sept, dix, un, deux, onze, trois, quatre, huit, douze.

.wrapper {
  reading-flow: grid-columns;
}

Vous pouvez également essayer d'utiliser grid-order. L'ordre de sélection reste de Un à Douze. En effet, aucun ordre de CSS n'avait été défini pour les articles.

Un conteneur de bloc utilisant reading-order

La propriété reading-order vous permet de spécifier le moment où un élément doit être visité dans le flux de lecture, en remplaçant l'ordre défini par la propriété reading-flow. Elle ne prend effet que sur un conteneur de flux de lecture valide, lorsque la propriété reading-flow n'est pas normal.

.wrapper {
  display: block;
  reading-flow: source-order;
}

.top {
  reading-order: -1;
  inset-inline-start: 50px;
  inset-block-start: 50px;
}

Le conteneur de bloc suivant contient cinq éléments. Il n'existe aucune règle de mise en page qui réorganise les éléments par rapport à leur ordre source, mais il existe un élément hors flux qui doit être visité en premier.

<div class="wrapper">
  <a href="#">Item 1</a>
  <a href="#">Item 2</a>
  <a href="#">Item 3</a>
  <a href="#">Item 4</a>
  <a class="top" href="#">Item 5</a>
</div>

En définissant la reading-order de cet élément sur -1, l'ordre de mise au point le visite en premier, avant de revenir à l'ordre source pour le reste des éléments du flux de lecture.

Vous trouverez d'autres exemples sur le site chrome.dev.

Interaction avec tabindex

Historiquement, les développeurs ont utilisé l'attribut global HTML tabindex pour rendre les éléments HTML sélectionnables et déterminer l'ordre relatif de la navigation séquentielle au clavier. Toutefois, cet attribut présente de nombreux inconvénients et problèmes d'accessibilité. Le principal problème est que la navigation au clavier ordonnée par tabindex créée à l'aide d'un tabindex positif n'est pas reconnue par l'arborescence d'accessibilité. Si vous l'utilisez de manière incorrecte, vous risquez d'obtenir un ordre de mise au point saccadé qui ne correspond pas à l'expérience sur un lecteur d'écran. Pour résoudre ce problème, suivez l'ordre à l'aide de l'attribut HTML aria-owns.

Dans l'exemple de flex précédent, pour obtenir le même résultat qu'avec reading-flow: flex-visual, vous pouvez procéder comme suit.

<div class="box" aria-owns="one three two">
  <a href="#" tabindex="1" id="one">One</a>
  <a href="#" tabindex="3" id="two">Two</a>
  <a href="#" tabindex="2" id="three">Three</a>
</div>

Mais que se passe-t-il si un autre élément en dehors du conteneur possède également tabindex=1 ? Ensuite, tous les éléments avec tabindex=1 seront visités ensemble, avant de passer à la valeur tabindex incrémentielle suivante. Cette navigation séquentielle saccadée nuit à l'expérience utilisateur. C'est pourquoi les experts en accessibilité recommandent d'éviter les valeurs positives pour l'attribut tabindex. Nous avons essayé de résoudre ce problème lors de la conception de reading-flow.

Un conteneur dont la propriété reading-flow est définie devient propriétaire d'une portée de focus. Cela signifie qu'il limite la navigation séquentielle au clavier pour visiter chaque élément à l'intérieur du conteneur avant de passer à l'élément pouvant être sélectionné suivant dans un document Web. De plus, ses enfants directs sont ordonnés à l'aide de la propriété reading-flow, et les tabindex positifs sont ignorés à des fins d'ordonnancement. Il est toujours possible de définir un tabindex positif sur les descendants d'un élément de flux de lecture.

Notez qu'un élément avec display: contents qui hérite de la propriété reading-flow de son parent de mise en page sera également un conteneur de flux de lecture valide. Tenez-en compte lorsque vous concevez votre site. Pour en savoir plus, consultez notre demande d'avis sur reading-flow et display: contents.

Recevoir des informations

Testez les exemples de cet article et les exemples reading-flow sur chrome.dev, puis utilisez ces propriétés CSS sur vos sites. Si vous avez des commentaires, signalez-les comme problème dans le dépôt GitHub du groupe de travail CSS. Si vous avez des commentaires spécifiques sur le comportement de l'index de tabulation et de la portée de la sélection, signalez-le comme problème dans le dépôt GitHub HTML WHATNOT. N'hésitez pas à nous faire part de vos commentaires sur cette fonctionnalité.