Utilizzare il flusso di lettura CSS per la navigazione sequenziale logica dello stato attivo

Data di pubblicazione: 1° maggio 2025

Le proprietà CSS reading-flow e reading-order sono disponibili a partire da Chrome 137. Questo post spiega i motivi alla base del design di queste proprietà e alcuni dettagli brevi per iniziare a utilizzarle.

Metodi di layout come grid e flex hanno trasformato lo sviluppo frontend, tuttavia la loro flessibilità può causare un problema per alcuni utenti. È molto facile creare una situazione in cui l'ordine visivo non corrisponde all'ordine dell'origine nell'albero DOM. Poiché questo ordine delle origini è quello seguito dal browser se navighi nel sito utilizzando una tastiera, alcuni utenti potrebbero riscontrare salti imprevisti mentre navigano in una pagina.

Le proprietà reading-flow e reading-order sono state progettate e aggiunte alla specifica CSS Display per provare a risolvere questo problema di lunga data.

reading-flow

La proprietà CSS reading-flow controlla l'ordine in cui gli elementi in un layout flessibile, a griglia o a blocchi vengono esposti agli strumenti di accessibilità e il modo in cui vengono attivati utilizzando metodi di navigazione sequenziale lineari.

Accetta un valore di parola chiave, con un valore predefinito di normal, che mantiene il comportamento di ordinamento degli elementi nell'ordine DOM. Per utilizzarlo all'interno di un contenitore flessibile, imposta il valore su flex-visual o flex-flow. Per utilizzarlo all'interno di un contenitore della griglia, imposta il valore su grid-rows, grid-columns o grid-order.

reading-order

La proprietà CSS reading-order ti consente di eseguire manualmente l'override dell'ordine degli elementi all'interno di un contenitore del flusso di lettura. Per utilizzare questa proprietà all'interno di un contenitore di tipo grid, flex o blocco, imposta il valore reading-flow del contenitore su source-order e imposta reading-order del singolo elemento su un valore intero.

Esempio in flexbox

Ad esempio, potresti avere un contenitore con layout flessibile con tre elementi in ordine inverso delle righe e voler utilizzare la proprietà order per rimescolare l'ordine.

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

Puoi provare a navigare tra questi elementi utilizzando il tasto TAB per trovare l'elemento acquisibile successivo e i tasti TAB+MAIUSC per trovare l'elemento acquisibile precedente. Seguono gli articoli nell'ordine originale: Uno, Due, Tre.

Dal punto di vista dell'utente finale, questo non ha senso e può essere molto confusionario. Lo stesso accade se utilizziamo uno strumento di navigazione spaziale per l'accessibilità per spostarci nella pagina.

Per risolvere il problema, imposta la proprietà reading-flow:

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

L'ordine di messa a fuoco ora è: Uno, Tre, Due. È lo stesso ordine visivo che otterresti se leggessi in inglese da sinistra a destra.

Se invece preferisci mantenere l'ordine di attivazione come previsto inizialmente, in ordine inverso, puoi impostare:

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

L'ordine di messa a fuoco ora è l'ordine flex inverso: Due, Tre, Uno. In entrambi i casi, viene presa in considerazione la proprietà CSS order.

Esempio con layout a griglia

Per capire come funziona in una griglia, immagina di creare un layout con elementi posizionati automaticamente in una griglia CSS con dodici aree attivabili.

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

Il quinto elemento figlio deve occupare lo spazio più grande in alto, seguito dal secondo elemento figlio verso la metà della griglia. Tutti gli altri elementi secondari possono essere inseriti automaticamente all'interno della griglia seguendo un modello di colonna.

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

Prova a spostarti tra questi elementi utilizzando il tasto TAB per trovare l'elemento successivo acquisibile e i tasti TAB+Maiusc per trovare l'elemento acquisibile precedente. Seguono gli articoli nell'ordine originale: da 1 a 12.

Per risolvere il problema, imposta la proprietà reading-flow:

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

L'ordine di messa a fuoco ora è: Cinque, Uno, Tre, Due, Quattro, Sei, Sette, Otto, Nove, Dieci, Undici, Dodici. Segue l'ordine visivo, riga per riga.

Se vuoi che il flusso di lettura segua l'ordine delle colonne, puoi utilizzare il valore della parola chiave grid-columns. L'ordine di messa a fuoco diventa Cinque, Sei, Nove, Sette, Dieci, Uno, Due, Undici, Tre, Quattro, Otto, Dodici.

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

Puoi anche provare a utilizzare grid-order. L'ordine di messa a fuoco rimane da 1 a 12. Questo perché non è stato impostato alcun ordine CSS per nessun articolo.

Un contenitore di blocchi che utilizza reading-order

La proprietà reading-order consente di specificare quando nel flusso di lettura un elemento deve essere visitato, sostituendo l'ordine impostato dalla proprietà reading-flow. Ha effetto solo su un contenitore del flusso di lettura valido, quando la proprietà reading-flow non è normal.

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

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

Il seguente contenitore di blocchi contiene cinque elementi. Non esistono regole di layout che riordinano gli elementi dall'ordine di origine, ma è presente un elemento fuori flusso che deve essere visitato per primo.

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

Se imposti reading-order su -1 per questo elemento, l'ordine di messa a fuoco lo visita prima prima di tornare all'ordine di origine per il resto degli elementi del flusso di lettura.

Puoi trovare altri esempi sul sito chrome.dev.

Interazione con tabindex

In passato, gli sviluppatori utilizzavano l'attributo globale HTML tabindex per rendere gli elementi HTML accessibili e determinare l'ordine relativo per la navigazione sequenziale con il fuoco. Tuttavia, questo attributo presenta molti svantaggi e problemi di accessibilità. Il problema principale è che la navigazione con il fuoco in ordine di tabindex creata utilizzando un valore tabindex positivo non è riconosciuta dall'albero di accessibilità. Se usato in modo errato, potresti ritrovarti con un ordine di attivazione discontinuo che non corrisponde all'esperienza su uno screen reader. Per risolvere il problema, monitora l'ordinamento utilizzando l'attributo HTML aria-owns.

Nell'esempio di flex precedente, per ottenere lo stesso risultato dell'utilizzo di reading-flow: flex-visual, puoi procedere nel seguente modo.

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

Ma cosa succede se un altro elemento esterno al contenitore ha anche tabindex=1? Successivamente, tutti gli elementi con tabindex=1 verranno visitati insieme, prima di passare al valore tabindex incrementale successivo. Questa navigazione sequenziale discontinua porterà a un'esperienza utente negativa. Pertanto, gli esperti di accessibilità consigliano di evitare valori positivi per tabindex. Abbiamo provato a risolvere il problema durante la progettazione di reading-flow.

Un contenitore con la proprietà reading-flow impostata diventa un proprietario dell'ambito di attenzione. Ciò significa che l'ambito della navigazione sequenziale dello stato attivo è visitare ogni elemento all'interno del contenitore prima di passare all'elemento attivabile successivo in un documento web. Inoltre, i relativi elementi secondari diretti sono ordinati utilizzando la proprietà reading-flow e gli elementi con tabindex positivo vengono ignorati ai fini dell'ordinamento. È ancora possibile impostare un valore tabindex positivo sui discendenti di un elemento del flusso di lettura.

Tieni presente che un elemento con display: contents che eredita la proprietà reading-flow dal layout principale sarà anche un contenitore del flusso di lettura valido. Tienilo presente quando progetti il tuo sito. Scopri di più nella nostra richiesta di feedback su reading-flow e display: contents.

Contattaci

Prova gli esempi in questo post e negli reading-flow esempi su chrome.dev e utilizza queste proprietà CSS sui tuoi siti. Se hai un feedback, segnalalo come problema nel repo GitHub del gruppo di lavoro CSS. Se hai un feedback specifico sul comportamento di ambito di tabindex e focus, segnalalo come problema nel repo GitHub HTML WHATNOT. Saremo lieti di ricevere il tuo feedback su questa funzionalità.