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 informations pour vous aider à vous lancer.

Les méthodes de mise en page telles que la grille et la flexibilité ont transformé le développement du frontend. Toutefois, leur flexibilité peut poser problème pour certains utilisateurs. Il est très facile de créer une situation où l'ordre visuel ne correspond pas à l'ordre source dans l'arborescence DOM. Étant donné que le navigateur suit cet ordre de sources 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 aux spécifications d'affichage CSS 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 flex, en grille ou en bloc sont exposés aux outils d'accessibilité et la façon dont ils sont mis au point à l'aide de méthodes de navigation séquentielle linéaire.

Il prend une valeur de mot clé, avec la valeur par défaut normal, qui conserve le comportement d'ordonnancement 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 parcours de lecture. Pour utiliser cette propriété dans un conteneur de grille, de flex ou de 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 entier.

Exemple dans Flexbox

Par exemple, vous pouvez avoir un conteneur de mise en page Flex avec trois éléments dans l'ordre des lignes inverse et vous souhaitez é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 naviguer dans ces éléments à l'aide de la touche TABULATION pour trouver l'élément sélectionnable suivant et des touches TABULATION+MAJ pour trouver l'élément sélectionnable précédent. Les éléments sont affichés dans l'ordre de la source: un, deux, trois.

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

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

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

L'ordre de mise au point est désormais le suivant: un, trois, deux. Il s'agit de 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 sélection est désormais l'ordre inverse de flex: deux, trois, un. Dans les deux cas, la propriété CSS order est prise en compte.

Exemple avec une disposition en grille

Pour comprendre comment cela fonctionne dans une grille, imaginez que vous créez une mise en page avec des éléments placés automatiquement dans une grille CSS avec douze zones sélectionnables.

<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 l'espace le plus grand 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 naviguer dans ces éléments à l'aide de la touche TABULATION pour trouver l'élément sélectionnable suivant et des touches TABULATION+MAJ pour trouver l'élément sélectionnable précédent. Les éléments sont affichés dans l'ordre de la 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 mise au point est désormais le suivant: cinq, un, trois, deux, quatre, six, sept, huit, neuf, dix, onze et douze. Il suit l'ordre visuel, ligne par ligne.

Si vous souhaitez que le flux de lecture suive plutôt l'ordre des colonnes, vous pouvez utiliser la valeur du mot clé grid-columns. L'ordre de mise au point 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 CSS n'a été défini pour aucun article.

Conteneur de blocs à l'aide de reading-order

La propriété reading-order vous permet de spécifier à quel moment dans le flux de lecture un élément doit être consulté, 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. Aucune règle de mise en page ne réorganise les éléments en fonction de leur ordre source, mais un élément hors flux doit être consulté 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 reading-order sur -1 pour cet élément, 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.

Pour en savoir plus, consultez le site chrome.dev.

Interaction avec l'attribut tabindex

Historiquement, les développeurs utilisaient l'attribut global HTML tabindex pour rendre les éléments HTML sélectionnables et déterminer l'ordre relatif pour la navigation séquentielle de la sélection. Toutefois, cet attribut présente de nombreux inconvénients et des problèmes d'accessibilité. Le principal problème est que la navigation de sélection basée sur l'index de tabulation créée à l'aide d'un index de tabulation positif n'est pas reconnue par l'arborescence d'accessibilité. Si vous ne l'utilisez pas correctement, vous risquez d'obtenir un ordre de sélection 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 que celui obtenu 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 d'index de tabulation incrémentielle suivante. Cette navigation séquentielle saccadée nuit à l'expérience utilisateur. Par conséquent, les experts en accessibilité recommandent d'éviter les tabindex positifs. 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 du champ d'application de la sélection. Cela signifie qu'il définit la navigation séquentielle de la sélection pour visiter chaque élément du conteneur avant de passer à l'élément suivant pouvant être sélectionné dans un document Web. De plus, ses enfants directs sont triés à l'aide de la propriété "reading-flow", et les tabindex positifs sont ignorés à des fins de tri. Il est toujours possible de définir un tabindex positif sur les descendants d'un élément de parcours 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 est également un conteneur de flux de lecture valide. Gardez cela à l'esprit lorsque vous concevez votre site. Pour en savoir plus, consultez notre demande de commentaires sur reading-flow et display: contents.

Recevoir des informations

Essayez les exemples de cet article et des exemples reading-flow sur chrome.dev, et utilisez ces propriétés CSS sur vos sites. Si vous avez des commentaires, signalez-les en tant que 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 du champ d'application du focus, signalez-le comme problème dans le dépôt GitHub HTML WHATNOT. Votre avis sur cette fonctionnalité nous intéresse.