Step 1 — What the Screen Reader Actually Receives

Goal

Stop reasoning about markup and start reading the accessibility tree the browser computes.

Predict first

The same visual UI — header, nav, heading, paragraph, button, data table, footer — built three ways:

  • semantic HTML (<header> <nav> <h1> <button> <table>)
  • div soup (<div class="btn" onclick>)
  • div + ARIA (<div role="button" tabindex="0">)

Predict for each: landmarks exposed, headings, interactive elements, keyboard-focusable elements, and which produces the most markup.

Most people predict semantic HTML is the most verbose. Commit before running.

Run

cd src && npm install && npm run a11y-tree

Expected output:

  variant        | AX nodes | named | landmarks | headings | interactive | table roles | focusable
  semantic HTML  |       56 |    38 |         4 |        2 |           3 |           7 |        3
  div soup       |       46 |    24 |         0 |        0 |           0 |           0 |        0
  div + ARIA     |       48 |    33 |         4 |        2 |           3 |           7 |        3

  markup size (normalised bytes):
    semantic HTML    459  (1.00x semantic)
    div soup         634  (1.38x semantic)
    div + ARIA       778  (1.69x semantic)

What just happened

Div soup exposes nothing. Zero landmarks, zero headings, zero controls. A screen-reader user has no way to navigate to a region, jump by heading, or list the controls — the three primary navigation modes. The page is a wall of undifferentiated text.

And it costs 38% more markup. This is the result that changes minds: div soup is not a shortcut that trades accessibility for speed of writing. It is more to write and less to use.

ARIA rebuilds the tree at 69% more markup — and only the tree. Look at the focusable column: the ARIA variant reaches 3 only because tabindex="0" was declared on every one. ARIA changed what is announced; it granted no behaviour. Still missing versus semantic HTML:

  • Enter/Space activation (must be implemented and tested)
  • disabled semantics
  • form participation
  • automatic accessible-name computation

ARIA describes. Elements behave.

Why the tree and not an audit tool: the div soup variant has no contrast failures, no missing alt text and no invalid ARIA. It would score well on many automated audits while exposing zero controls. Only the tree shows the problem — the concrete limit-of-automation lesson fe-24 builds on.

Checkpoint

docs/verification.md Checkpoints 1 and 2.

Do this by hand too

Open DevTools → Elements → Accessibility → enable Full-page accessibility tree, and look at a page you own. Navigate it by landmark and by heading. If you cannot, neither can your users.