Usar o fluxo de leitura do CSS para navegação sequencial lógica

Publicado em 1º de maio de 2025

As propriedades CSS reading-flow e reading-order estão disponíveis a partir do Chrome 137. Esta postagem explica os motivos por trás do design dessas propriedades e alguns detalhes para você começar a usá-las.

Métodos de layout, como grade e flex, transformaram o desenvolvimento de front-end, mas a flexibilidade deles pode causar problemas para alguns usuários. É muito fácil criar uma situação em que a ordem visual não corresponde à ordem de origem na árvore DOM. Como essa ordem de origem é a que o navegador segue se você navegar pelo site usando um teclado, alguns usuários podem encontrar saltos inesperados ao navegar por uma página.

As propriedades reading-flow e reading-order foram projetadas e adicionadas à especificação de exibição do CSS para tentar resolver esse problema de longa data.

reading-flow

A propriedade CSS reading-flow controla a ordem em que os elementos em um layout flexível, de grade ou de bloco são expostos às ferramentas de acessibilidade e como eles são focados usando métodos de navegação sequencial linear.

Ele usa um valor de palavra-chave, com um padrão de normal, que mantém o comportamento de ordenar elementos na ordem do DOM. Para usá-lo em um contêiner flexível, defina o valor como flex-visual ou flex-flow. Para usá-lo em um contêiner de grade, defina o valor como grid-rows, grid-columns ou grid-order.

reading-order

A propriedade CSS reading-order permite que você substitua manualmente a ordem dos itens em um contêiner de fluxo de leitura. Para usar essa propriedade em um contêiner de grade, flex ou bloco, defina o valor reading-flow no contêiner como source-order e defina o reading-order do item individual como um valor inteiro.

Exemplo em flexbox

Por exemplo, você pode ter um contêiner de layout flexível com três elementos na ordem inversa das linhas e também querer usar a propriedade de ordem para reorganizar essa ordem.

<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;
}

Você pode navegar por esses elementos usando a tecla TAB para encontrar o próximo elemento focalizável e as teclas TAB+SHIFT para encontrar o elemento focalizável anterior. Isso segue os itens na ordem da fonte: Um, Dois, Três.

Do ponto de vista do usuário final, isso não faz sentido e pode ser muito confuso. O mesmo acontece se usarmos uma ferramenta de navegação espacial de acessibilidade para navegar pela página.

Para corrigir isso, defina a propriedade reading-flow:

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

A ordem de foco agora é: Um, Três, Dois. Essa é a mesma ordem visual que você teria se estivesse lendo em inglês da esquerda para a direita.

Se você preferir manter a ordem de foco como foi originalmente, na ordem inversa, defina:

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

A ordem de foco agora é a ordem flex reversa: dois, três, um. Em ambos os casos, a propriedade order do CSS é considerada.

Exemplo com layout de grade

Para entender como isso funciona em uma grade, imagine que você está criando um layout com itens autoajustados da grade CSS com 12 áreas de foco.

<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>

Você quer que o quinto filho ocupe o maior espaço na parte de cima, seguido pelo segundo filho em direção ao meio da grade. Todas as outras filhas podem ser colocadas automaticamente na grade seguindo um modelo de coluna.

.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;
}

Tente navegar por esses elementos usando a tecla TAB para encontrar o próximo elemento focalizável e as teclas TAB + SHIFT para encontrar o elemento focalizável anterior. Isso segue os itens na ordem da fonte: um a doze.

Para corrigir isso, defina a propriedade reading-flow:

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

A ordem de foco agora é: Cinco, Um, Três, Dois, Quatro, Seis, Sete, Oito, Nove, Dez, Onze, Doze. Ele segue a ordem visual, linha por linha.

Se você quiser que o fluxo de leitura siga a ordem das colunas, use o valor da palavra-chave grid-columns. A ordem de foco passa a ser Cinco, Seis, Nove, Sete, Dez, Um, Dois, Onze, Três, Quatro, Oito, Doze.

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

Também é possível usar grid-order. A ordem de foco permanece como Um a Doze. Isso ocorre porque não havia uma ordem de CSS definida em nenhum item.

Um contêiner de bloco usando reading-order

A propriedade reading-order permite especificar quando um item precisa ser visitado no fluxo de leitura, substituindo a ordem definida pela propriedade reading-flow. Ela só entra em vigor em um contêiner de fluxo de leitura válido, quando a propriedade reading-flow não é normal.

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

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

O contêiner de bloco a seguir contém cinco itens. Não há regras de layout que reordenem os elementos da ordem de origem, mas há um item fora do fluxo que precisa ser visitado primeiro.

<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>

Ao definir o reading-order do item como -1, a ordem de foco o visita primeiro antes de retornar à ordem de origem para o restante dos itens do fluxo de leitura.

Confira mais exemplos no site chrome.dev.

Interação com tabindex

Historicamente, os desenvolvedores usaram o atributo global tabindex do HTML para tornar os elementos HTML com foco e determinar a ordem relativa para a navegação sequencial de foco. No entanto, esse atributo tem muitas desvantagens e preocupações de acessibilidade. A principal preocupação é que a navegação de foco ordenada por tabindex criada usando tabindex positivo não é reconhecida pela árvore de acessibilidade. Quando usado incorretamente, você pode acabar com uma ordem de foco irregular que não corresponde à experiência em um leitor de tela. Para corrigir isso, rastreie a ordem usando o atributo HTML aria-owns.

No exemplo de flex anterior, para ter o mesmo resultado que o uso de reading-flow: flex-visual, você pode fazer o seguinte.

<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>

Mas o que acontece se outro elemento fora do contêiner também tiver tabindex=1? Em seguida, todos os elementos com tabindex=1 serão visitados juntos antes de passarmos para o próximo valor incremental de tabindex. Essa navegação sequencial irregular resulta em uma experiência ruim para o usuário. Por isso, especialistas em acessibilidade recomendam evitar tabindex positivo. Tentamos corrigir isso ao projetar o reading-flow.

Um contêiner com a propriedade reading-flow definida se torna um proprietário do escopo de foco. Isso significa que ele define o escopo da navegação sequencial do foco para visitar todos os elementos dentro do contêiner antes de passar para o próximo elemento com foco em um documento da Web. Além disso, os filhos diretos são ordenados usando a propriedade reading-flow, e o tabindex positivo é ignorado para fins de ordenação. Ainda é possível definir um tabindex positivo nos descendentes de um item de fluxo de leitura.

Um elemento com display: contents que herda a propriedade reading-flow do layout pai também será um contêiner de fluxo de leitura válido. Considere isso ao projetar seu site. Leia mais sobre isso na nossa solicitação de feedback sobre reading-flow e display: contents.

Conte para nós

Teste os exemplos desta postagem e nos exemplos de reading-flow no chrome.dev e use essas propriedades CSS nos seus sites. Se você tiver algum feedback, envie-o como um problema no repositório do GitHub do grupo de trabalho do CSS. Se você tiver feedback específico sobre o comportamento de escopo de foco e tabindex, envie como um problema para o repositório do HTML WHATNOT no GitHub. Queremos saber sua opinião sobre esse recurso.