Test your website →

Blog

Reading Order: When Your Visual Layout Lies to Assistive Tech

Every page has two orders — the one you see and the one in the code — and CSS makes it easy for them to disagree.

Every web page is really two pages. There’s the one you see: elements arranged in space, price next to product, label above input, sidebar to the right. And there’s the one in the code: a single file of markup where every element comes strictly before or after every other one. Sighted users read the first page. Screen readers, keyboards, and search engines read the second. Most of the time the two pages agree, and nobody thinks about it. The interesting bugs happen when they don’t.

For most of the web’s history they couldn’t disagree much, because layout was mostly a consequence of source order. Things appeared roughly where they sat in the file. Then CSS got powerful. Flexbox has a property that reorders items visually without touching the markup. Grid lets you place any element in any cell regardless of where it appears in the source. Absolute positioning has let you put anything anywhere for decades. These are genuinely good tools. But every one of them lets the visual page drift away from the coded page, and only one of those pages is the truth as far as assistive technology is concerned. A screen reader reads the document in source order, start to finish. It does not look at the screen. If your CSS says the price appears above the product name but your markup says it comes three sections later, the blind user hears it three sections later. The layout is, in a literal sense, lying about the document.

The damage is worst where order carries meaning. A checkout page where the “place order” button visually sits under the order summary, but lives at the top of the markup, gets announced before the user has heard what they’re buying. A form where the hint text (“we’ll never share your email”) is positioned under the field but placed elsewhere in the source arrives as a non sequitur, attached to nothing. Pairs are the classic case: image and caption, question and answer, label and value. Visually, proximity binds them. In the source, they might be strangers, and then the screen reader user hears a list of answers with the questions somewhere else entirely.

Keyboard users get their own version of this bug, and you don’t need a screen reader to see it. Tab order follows source order too. If CSS has rearranged a row of buttons, pressing Tab makes focus jump around the screen in an order that looks random: third button, first, fourth, second. The accessibility guidelines call the underlying requirement “meaningful sequence” and “focus order,” but the plain-English version is just this: the order in the file should be an order that makes sense, because for a lot of your users the file order is the only order there is.

The insidious thing about reading-order bugs is who creates them. Nobody sets out to scramble a page. What happens is that a designer moves an element in a mockup, and the developer has two ways to comply: move it in the markup, or leave the markup alone and move it with CSS. The CSS route is often less work, less likely to break something else, easier to ship on a Friday. Each such shortcut is individually defensible. Ten of them later, the visual page and the coded page have quietly diverged, and no test failed, because the page looks perfect. This is the general shape of many accessibility failures: not malice, not even ignorance exactly, but an invisible cost paid by users who aren’t in the room.

There’s a rule of thumb that prevents most of it. Make the source order match the reading order, and let CSS handle only appearance, not sequence. When a design genuinely requires elements to sit in a different visual arrangement on different screen sizes, prefer restructuring the markup so that its order still tells the story, and reach for CSS reordering only when the order truly doesn’t matter, like decorative cards that could shuffle freely without anyone noticing.

Testing for it is cheap in a way that’s almost funny. One method: press Tab repeatedly through your page and watch where the focus outline goes. If it ever leaps backward or hopscotches across the screen, your two pages disagree. Another: select all the text on the page and paste it into a plain text file, or disable CSS entirely, and read what’s left top to bottom. That linear text is quite close to what a screen reader user gets. If the story it tells is scrambled, you’ve found the bug. When I was building GazeSite I made the scanner look at the raw HTML alongside the rendered screenshot for exactly this reason: the screenshot shows the page you designed, the markup shows the page you actually shipped, and the users you’re most likely to lose are the ones who only ever receive the second one. A page isn’t finished when it looks right. It’s finished when it reads right, too.

More articles

← All posts