CSS Reading Flow: Logical Order for Grid and Flex Layouts

The CSS reading-flow property (Chrome 137+) solves the accessibility problem where visual order (set by CSS Grid or Flexbox) diverges from DOM order — causing keyboard focus and screen reader reading order to follow the source order rather than the visual layout. With reading-flow, focus navigation follows the visual order without requiring JavaScript or DOM reordering.

Problem: CSS Grid and Flexbox lay out items visually in a different order from the DOM — order and grid-template-areas can move items visually without changing the HTML order — causing a mismatch between visual reading order and keyboard tab order for screen reader users.

Solution: Use the CSS reading-flow property (shipping in Chrome 137+) to declare the intended reading order of a flex or grid container: reading-flow: flex-visual or reading-flow: grid-rows. The browser adjusts keyboard focus and accessibility tree order to match, without requiring DOM reordering.


The examples below show reading-flow on a grid layout, a flex row with reversed visual order, a card grid where the visual order changes at a breakpoint, and how to apply it in a WordPress block theme for accessible reordered layouts.


/* ── 1. reading-flow: normal (default) vs grid-rows ──────────────────────
   Without reading-flow, Tab key follows DOM source order.
   reading-flow: grid-rows makes Tab follow grid row-by-row left-to-right. */

.grid-layout {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    reading-flow: grid-rows;   /* Tab follows visual row order */
}

/* ── 2. Flex container: reversed visual order ────────────────────────────
   Without reading-flow, Tab on a flex-direction:row-reverse container
   moves right-to-left (DOM order), not left-to-right (visual order).     */
.nav-reversed {
    display: flex;
    flex-direction: row-reverse;
    reading-flow: flex-visual;  /* Tab follows visual left-to-right order */
}

/* ── 3. Grid with named areas and responsive reordering ─────────────────── */
.page-layout {
    display: grid;
    grid-template-areas:
        "header header"
        "sidebar main"
        "footer footer";
    reading-flow: grid-order;   /* follows grid-area / order properties */
}

@media (max-width: 768px) {
    .page-layout {
        grid-template-areas:
            "header"
            "main"        /* main comes before sidebar on mobile */
            "sidebar"
            "footer";
        /* reading-flow: grid-order still works — Tab now follows mobile visual order */
    }
}

/* ── 4. WordPress block theme: accessible columns block ────────────────── */
.wp-block-columns {
    reading-flow: flex-visual;
}

/* When columns are reversed via is-style-* modifier */
.wp-block-columns.is-style-reversed {
    flex-direction: row-reverse;
    reading-flow: flex-visual;  /* Tab still goes left-to-right visually */
}

/* ── 5. Values summary ───────────────────────────────────────────────────
   normal          → default (DOM order)
   flex-visual     → follows visual flex order
   flex-flow       → follows flex-flow direction
   grid-rows       → left-to-right, row by row
   grid-columns    → top-to-bottom, column by column
   grid-order      → follows the CSS order property / grid-area placement */


NOTE: reading-flow only affects focus navigation order for keyboard users — it has no effect on DOM order (which screen readers may still follow depending on their reading mode); for full accessibility, pair reading-flow with correct semantic HTML and test with both keyboard navigation and a screen reader in document reading mode.