Reclaiming the Flow: Mastering Visual vs. DOM Order with @reading-order
Your CSS is lying to some of your users. Here's the property that fixes it.
The Accessibility Gap: When Visual Order Betrays Logical Order
For a long time, developers have been able to put together the strangest of layouts that have come from the dark corners of the design team with very little pushback. Properties like flex-direction, grid-template-areas and the order property have given us a monumental amount of control when dealing with the visual presentation of the elements on the screen, and we can rearrange content to adapt to different screen sizes and user preference with little effort.
Sometimes however, that ability comes with a sidestep of accessibility and performance concerns, and that really isn’t acceptable at all. We would warn that a layout might affect accessibility, but in the worst cases it can met with a shrug, depending on how much the team cares about providing accessible solutions in the first place. In my current position, accessibility concerns are met with a lot of discussion and push back to find a better path - so the prior ‘shrug’ example is not a reflection of how our projects are dealt with. The main challenge has been that while we can change how elements look on the screen, their true order in the DOM is the ‘golden truth’. We’ll go through a couple of examples to help illustrate this.
Example 1: Our card layout
If we have for example, a traditional card layout that has 3 elements; a date (the highest semantic priority), a title, and an image (the lowest semantic priority), and we’ve used CSS to reorder them differently (let’s say; the image, then the date, then the title). We would have this;
.reading-order-card date {
order: 2;
}
.reading-order-card span,
.reading-order-card > a {
order: 3;
}
.reading-order-card img {
order: 1;
}
Card heading
Laborum sint laborum nostrud est. Est exercitation et occaecat ut proident non voluptate et. Laborum non id voluptate tempor ea anim anim eu irure laborum velit labore ullamco. Non ipsum labore consequat adipisicing amet ut reprehenderit.
Visually, we’ve got our card layout looking like this; an image, then a date, then a title. Pretty generic stuff, but when a screen reader user traverses this layout, the order of the content is not what we would expect. The image is announced first, then the date, then the title. This is because the screen reader is reading the content in the order of the DOM, not the visual order.
Visual order vs DOM order: the gap your users fall into
When CSS reorders content visually, keyboard and screen reader users still follow the DOM. Use Tab to navigate the cards below and feel the difference.
Layout
What keyboard/screen reader users get: Article A → Article B → CTA
The CTA appears first visually via
order: 1 - but it's third in
the DOM. Tab key follows the DOM.
/* Visual order achieved with CSS order - */
/* but DOM (and focus) order is unchanged */
.card-a { order: 2; } /* DOM: 1st, visual: 2nd */
.card-b { order: 3; } /* DOM: 2nd, visual: 3rd */
.card-cta { order: 1; } /* DOM: 3rd, visual: 1st ⚠️ */Tab focus sequence
Layout
Focus + reading order: CTA → Article A → Article B (now matches )
reading-flow: flex-visual on the container + reading-order integers on each child tell the browser's Accessibility Tree to follow visual
order instead of DOM order.
/* Same visual order - but now focus matches */
.cards {
display: flex;
reading-flow: flex-visual; /* ← on the container */
}
.card-a { order: 2; reading-order: 2; }
.card-b { order: 3; reading-order: 3; }
.card-cta { order: 1; reading-order: 1; }Tab focus sequence
How the orders map
| Card | DOM position | Visual position (order) | Focus position (reading-order) |
|---|---|---|---|
| CTA | 3rd | 1st | 1st |
| Article A | 1st | 2nd | 2nd |
| Article B | 2nd | 3rd | 3rd |
Example 2: Our grid layout
If we have for example, a layout that is 3 elements (Article A, Article B and a CTA) in that order in the DOM, and we’ve used CSS to reorder them differently (let’s say; the CTA, Article A and Article B). We would have this;
.reading-order-example-2 {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas:
"cta article-a article-b"
"article-c cta-2 article-d"
}
.reading-order-example-2 .reading-order-card--1 {
grid-area: article-a;
}
.reading-order-example-2 .reading-order-card--2 {
grid-area: article-b;
}
.reading-order-example-2 .reading-order-card--3 {
grid-area: cta;
}
.reading-order-example-2 .reading-order-card--4 {
grid-area: article-c;
}
.reading-order-example-2 .reading-order-card--5 {
grid-area: article-d;
}
.reading-order-example-2 .reading-order-card--6 {
grid-area: cta-2;
}
What’s the correct order for these examples? Visually they are correct - they’ve done what we want it to do in that specific order to appease our designer overlords. However, for a user navigating the site through the use of a screen reader or a keyboard, this might be a bit of a contradiction. Typically screen readers such as NVDA, JAWS or Voiceover traverse the DOM and read out the content as it is set there, disregarding any extra information that might be in place to reorder it, announcing the CTA, then the Article A, then the Article B in that order. If we use the tab key to traverse the DOM, it will once again follow the DOM order, rather than our re-ordered items. Try using the tab key on this page to navigate through the section above, and notice that the focus outline is applied to Article A before the CTA. So we can see by attempting to replicate our design and using order or grid-template-areas, that we’ve actually broken the accessibility of the page and left behind come accessibility debt to fix later on, and that debt increases with every time we use order or grid-template-areas and don’t account for the accessibility implications. That’s also just from a developer’s perspective, considering the user experience is even worse - users who rely on keyboard navigation or screen readers only have the DOM as their map and our CSS decisions often discard that map entirely.
Visual order vs DOM order: the gap your users fall into
When CSS reorders content visually, keyboard and screen reader users still follow the DOM. Use Tab to navigate the cards below and feel the difference.
Visual layout
DOM order: Feature(1) · Article A(2) · Article B(3) · CTA(4) - CTA is last in the DOM but placed top-left visually.
grid-template-areas, but it's the 4th item in the DOM. Tab key ignores grid
placement entirely - it follows DOM order. A keyboard user hits Feature →
Article A → Article B → CTA: the opposite of what the layout implies.
Live layout - try tabbing through
The hidden cost of visual reordering in modern CSS layouts
Every time we reach for order or grid-template-areas to move content around the screen, we're making a silent promise to sighted
users that we may be breaking for everyone else.
WCAG 2.4.3 and the focus order criterion
Focus order is a Level A requirement, meaning it applies to the broadest range of users and content types.
Read article →Testing keyboard navigation: a practical checklist
Tab through your layout. Does focus move in a logical sequence? Does it match what a sighted user would expect?
Read article →New: reading-flow & reading-order
Get started →Tab focus sequence
reading-flow: grid-rows to the container.
The browser now reads focus order row by row, matching the visual grid - CTA
→ Feature → Article A → Article B. DOM order is unchanged; only focus order
is corrected.
Live layout - try tabbing through
The hidden cost of visual reordering in modern CSS layouts
Every time we reach for order or grid-template-areas to move content around the screen, we're making a silent promise to sighted
users that we may be breaking for everyone else.
WCAG 2.4.3 and the focus order criterion
Focus order is a Level A requirement, meaning it applies to the broadest range of users and content types.
Read article →Testing keyboard navigation: a practical checklist
Tab through your layout. Does focus move in a logical sequence? Does it match what a sighted user would expect?
Read article →New: reading-flow & reading-order
Get started →Tab focus sequence
reading-flow corrects
the accessibility layer only.
The CSS
.editorial-grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas:
"cta feature" "art-a art-b";
reading-flow: grid-rows; /* ← one line fixes it */
}
/* DOM order: feature · art-a · art-b · cta */ /* Focus order after fix: cta → feature → art-a → art-b */ .cell-feature { grid-area: feature; }
.cell-art-a { grid-area: art-a; }
.cell-art-b { grid-area: art-b; }
.cell-cta { grid-area: cta; } /* DOM: last, visual: top-left */ How the orders map
| Card | DOM position | Visual position (order) | Focus position (reading-order) |
|---|---|---|---|
| CTA | 4th | top-left | 1st |
| Feature | 1st | top-right | 2nd |
| Article A | 2nd | btm-left | 3rd |
| Article B | 3rd | btm-right | 4th |
The Solution: reading-flow and reading-order
So how do we fix this? This design isn’t exactly a new trend, but being able to fix it whilst also being able to maintain the visual order of the elements is a bit of a challenge. There is either;
- an outcome where visual design flexibility is put aside in favor of accessibility leading to a less than ideal user experience/ugly design decision, or
- we over-engineer a solution to look to sync the DOM with the visual order to aid with our accessibility efforts, leading to some complex and fragile solutions.
Bit of a no-win situation really. Even worse, the difference between visual order and DOM order isn’t just an massive inconvenience, it’s also a W3C-recognized accessibility violation, specifically the WCAG 1.3.2: Meaningful Sequence and WCAG 2.4.3: Focus Order guidelines.
With these two principles in mind, it’s clear that our number one goal should be the consistency and predictability of the experience for all users. Breaking this, if it wasn’t clear enough by now which hopefully it is, can lead to confusion, frustration and ultimately exclusion. By using reading-flow and reading-order, we can allow for content that is presented the way our design is put together, and also meets the accessibility principles that we outlined above. All the while avoiding the pitfalls of using order or grid-template-areas, their accessibility implications and focus on only visually rearranging content.
It’s important to note at this stage that this isn’t to replace the use of order or grid-template-areas, if anything, it allows us to use them for purely visual purposes and still maintain the accessibility of the page knowing that they won’t fail WCAG guidelines.
reading-flow (on the container):
So, what is reading-flow? This property controls how the browser determines the default reading order of children that are with a flex, grid or block container. There are seperate applicable values that can be used on this property, depending on whether the container has one of those display properties set. These values are;
- normal (default): Follows DOM order.
- flex-visual: Prioritizes the visual order of flex items.
- flex-flow: Follows the logical flow of flex items (e.g., flex-direction: row-reverse would reverse the reading order).
- grid-rows: Reads grid items row by row.
- grid-columns: Reads grid items column by column.
- grid-order: Follows the explicit order values on grid items.
- source-order: Explicitly forces DOM order, even in grid/flex.
reading-order (on the items):
So if we have reading-flow to do this, what does reading-order do differently? Well reading-order provides an integer value - similar to how order is used - that allows a manual override of the reading order of individual items that are inside a reading-flow container. The lower the value, the higher the priority of reading order. If reading-flow is not set on the parent then any reading-order values set are not taken into account, and is also disregarded if the reading-flow container is set to normal or source-order. This is where the power of reading-order comes in, as it directly instructs the browser’s Accessibility Tree to follow the visual order, rather than the static DOM order. This means that for interactive elements, the keyboard focus order is automatically fixed, eliminating the need for fragile JavaScript solutions or manually setting tabindex values.
Best Practices and Considerations
When using these properties, it’s best to not overuse it. For accessibility, the default DOM order is always the best - referring back to our ‘golden truth’ comment earlier. If there was to be a recommendation, it would be to only use this when there’s a justified reason for the reordering of elements and if the design absolutely couldn’t be achieved without that reordering occurring - after all, it’s an enhancement to solve specific layout challenges.
When we look at the support at the top of this page, support is still sparse, but it’s getting better. As of March 2026, Chrome and Edge have support for reading-flow and reading-order. The progressive enhancement story is actually straightforward: browsers without support simply fall back to DOM order, which is the baseline behaviour anyway. No special fallback code needed - just make sure your DOM order is as logical as possible, and reading-flow becomes an enhancement on top of that. It’s important to communicate this to the team and the stakeholders, and to have a plan in place to test the site thoroughly with assistive technologies to ensure that the site is still accessible.
Conclusion
Sometimes visual design and accessibility butt heads, and they have done for years. Now, with the introduction of reading-flow and reading-order, this conflict can be significantly reduced. As developers, we no longer need to choose between a beautiful design and an accessible one. We’re finally getting the right tools to do this without complex JavaScript solutions or manual tabindex management. This is a win for everyone.
That being said, this is still a work in progress, and support is more sparse than it should be given the importance of the feature. To help push it forward, developers need to advocate for it - test it, report issues, and make the case for prioritising it. The next generation of web layouts should be both beautiful and universally accessible. We have the tools now. Let’s use them.
Resources
The spec is still evolving - these are the working drafts worth bookmarking if you want to track changes as browser support improves.