Publicado el 1 de mayo de 2025
Las propiedades reading-flow y reading-order de CSS están disponibles a partir de Chrome 137.
En esta publicación, se explican los motivos del diseño de estas propiedades y algunos detalles breves para que comiences a usarlas.
Los métodos de diseño, como la cuadrícula y el diseño flexible, transformaron el desarrollo de frontend. Sin embargo, su flexibilidad puede causar problemas para algunos usuarios. Es muy fácil crear una situación en la que el orden visual no coincide con el orden de la fuente en el árbol del DOM. Como este orden de la fuente es el que sigue el navegador si navegas por el sitio con un teclado, algunos usuarios pueden experimentar saltos inesperados mientras navegan por una página.
Las propiedades reading-flow y reading-order se diseñaron y agregaron a la especificación de CSS Display para intentar resolver este problema de larga data.
reading-flow
La propiedad reading-flow de CSS controla el orden en que los elementos de un diseño flexible, de cuadrícula o de bloque se exponen a las herramientas de accesibilidad y cómo se enfocan con los métodos de navegación secuencial lineal.
Toma un valor de palabra clave, con un valor predeterminado de normal, que mantiene el comportamiento de ordenar elementos en orden del DOM.
Para usarlo dentro de un contenedor flexible, establece su valor en flex-visual o flex-flow. Para usarlo dentro de un contenedor de cuadrícula, establece su valor en grid-rows, grid-columns o grid-order.
reading-order
La propiedad reading-order de CSS te permite anular manualmente el orden de los elementos dentro de un contenedor de flujo de lectura. Para usar esta propiedad dentro de un contenedor de cuadrícula, flexible o de bloque, establece el valor reading-flow en el contenedor como source-order y el reading-order del elemento individual en un valor entero.
Ejemplo en Flexbox
Por ejemplo, es posible que tengas un contenedor de diseño flexible con tres elementos en orden inverso de fila y que también quieras usar la propiedad order para reorganizar ese orden.
<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;
}
Puedes intentar navegar por estos elementos con la tecla TAB para encontrar el siguiente elemento enfocable y las teclas TAB + MAYÚSCULAS para encontrar el elemento enfocable anterior. Esto sigue el orden de los elementos en la fuente: Uno, Dos, Tres.
Desde la perspectiva del usuario final, esto no tiene sentido y puede ser muy confuso. Lo mismo sucede si usamos una herramienta de navegación espacial de accesibilidad para navegar por la página.
Para solucionar este problema, configura la propiedad reading-flow:
.box {
reading-flow: flex-visual;
}
El orden de enfoque ahora es: Uno, Tres, Dos. Es el mismo orden visual que obtendrías si leyeras en inglés de izquierda a derecha.
Si, en cambio, prefieres mantener el orden del enfoque tal como se pensó originalmente, en orden inverso, puedes establecer lo siguiente:
.box {
reading-flow: flex-flow;
}
El orden de enfoque ahora es el orden flexible inverso: Dos, Tres, Uno. En ambos casos, se tiene en cuenta la propiedad order del CSS.
Ejemplo con diseño de cuadrícula
Para ver cómo funciona esto en una cuadrícula, imagina que estás creando un diseño con elementos colocados automáticamente en la cuadrícula de CSS con doce áreas enfocables.
<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>
Quieres que el quinto elemento secundario ocupe el espacio más grande en la parte superior, seguido del segundo elemento secundario hacia el centro de la cuadrícula. Todos los demás elementos secundarios se pueden colocar automáticamente dentro de la cuadrícula siguiendo una plantilla de columna.
.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;
}
Intenta navegar por estos elementos con la tecla TAB para encontrar el siguiente elemento enfocable y las teclas TAB + MAYÚSCULAS para encontrar el elemento enfocable anterior. Sigue los elementos en el orden de la fuente: del uno al doce.
Para solucionar este problema, configura la propiedad reading-flow:
.wrapper {
reading-flow: grid-rows;
}
El orden de enfoque ahora es: Cinco, Uno, Tres, Dos, Cuatro, Seis, Siete, Ocho, Nueve, Diez, Once y Doce. Sigue el orden visual, fila por fila.
Si deseas que el flujo de lectura siga el orden de las columnas, puedes usar el valor de la palabra clave grid-columns. El orden de enfoque se convierte en Cinco, Seis, Nueve, Siete, Diez, Uno, Dos, Once, Tres, Cuatro, Ocho y Doce.
.wrapper {
reading-flow: grid-columns;
}
También puedes intentar usar grid-order. El orden de enfoque permanece como del uno al doce.
Esto se debe a que no se estableció ningún orden de CSS en ningún elemento.
Un contenedor de bloques que usa reading-order
La propiedad reading-order te permite especificar en qué momento del flujo de lectura se debe visitar un elemento, lo que anula el orden establecido por la propiedad reading-flow. Solo tiene efecto en un contenedor de flujo de lectura válido cuando la propiedad reading-flow no es normal.
.wrapper {
display: block;
reading-flow: source-order;
}
.top {
reading-order: -1;
inset-inline-start: 50px;
inset-block-start: 50px;
}
El siguiente contenedor de bloques contiene cinco elementos. No hay reglas de diseño que reordenen los elementos según su orden de origen, pero hay un elemento fuera del flujo que se debe visitar primero.
<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>
Si configuras el atributo reading-order de este elemento como -1, el orden de enfoque lo visitará primero antes de volver al orden de origen para el resto de los elementos del flujo de lectura.
Puedes encontrar más ejemplos en el sitio chrome.dev.
Interacción con tabindex
Históricamente, los desarrolladores han usado el atributo global tabindex de HTML para hacer que los elementos HTML sean enfocables y determinar el orden relativo para la navegación secuencial por enfoque. Sin embargo, este atributo tiene muchas desventajas y problemas de accesibilidad. La principal preocupación es que el árbol de accesibilidad no reconoce la navegación de enfoque ordenada por tabindex que se crea con tabindex positivo. Si se usa de forma incorrecta, es posible que el orden del enfoque sea errático y no coincida con la experiencia en un lector de pantalla. Para corregir eso, haz un seguimiento del ordenamiento con el atributo HTML aria-owns.
En el ejemplo anterior de flex, para obtener el mismo resultado que con reading-flow: flex-visual, puedes hacer lo siguiente.
<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>
Pero, ¿qué sucede si otro elemento fuera del contenedor también tiene tabindex=1?
Luego, se visitarán todos los elementos con tabindex=1 juntos, antes de pasar al siguiente valor de tabindex incremental. Esta navegación secuencial con saltos generará una mala experiencia del usuario. Por lo tanto, los expertos en accesibilidad recomiendan evitar el tabindex positivo. Intentamos corregir esto cuando diseñamos reading-flow.
Un contenedor que tiene establecida la propiedad reading-flow se convierte en propietario de un alcance de enfoque.
Esto significa que el alcance de la navegación secuencial con el foco se limita a visitar cada elemento dentro del contenedor antes de pasar al siguiente elemento enfocable en un documento web. Además, sus elementos secundarios directos se ordenan con la propiedad de flujo de lectura, y se ignoran los tabindex positivos para fines de ordenamiento. Aún es posible establecer un tabindex positivo en los elementos descendientes de un elemento de flujo de lectura.
Ten en cuenta que un elemento con display: contents que hereda la propiedad reading-flow de su elemento principal de diseño también será un contenedor de flujo de lectura válido. Ten esto en cuenta cuando diseñes tu sitio. Obtén más información al respecto en nuestra solicitud de comentarios sobre reading-flow y display: contents.
Envíanos tus comentarios
Prueba los ejemplos de esta publicación y los ejemplos de reading-flow en chrome.dev, y usa estas propiedades de CSS en tus sitios. Si tienes comentarios, plantéalos como un problema en el repositorio de GitHub del grupo de trabajo de CSS. Si tienes comentarios específicos sobre el comportamiento del alcance del enfoque y el tabindex, plantéalos como un problema en el repositorio de GitHub de HTML WHATNOT. Nos encantaría recibir tus comentarios sobre esta función.