Guide · CSS & Frontend

How Screen Readers Interpret Your HTML

Updated 2026-08-09 · 4 min read

A screen reader does not “look at the page.” It walks an accessibility tree: elements that expose a role, a name, a value, and a place in the document order. That tree is built from HTML (and ARIA), not from the fact that a div is bold and centered.

Screen Reader Preview is a way to see announcement-style output for a snippet you paste. It is not VoiceOver, NVDA, or JAWS. Use it early, then run a real reader on the real page. WCAG Checker is the rule pass next to it.

The accessibility tree, not the visual tree

Roles come from elements: <button> is a button, <a href> is a link, <h2> is a heading level 2, <input type="text"> is an edit field. A <div onclick> with a child SVG is a generic grouping until you add role="button" and a name and keyboard support. Prefer the real element.

Name is what gets spoken: button text, aria-label, associated <label>, image alt, figcaption in some cases. Value is the checkbox state, the slider number, the selected option.

Order is DOM order by default, not visual order from flex-direction: row-reverse or absolute positioning. If the visual first control is last in the DOM, keyboard and reader users meet it last. That is a common “CSS-only layout” bug.

aria-hidden="true" removes a subtree from the tree. Use it on decorative duplicates, not on the only copy of the price.

Headings as the table of contents

Screen-reader users jump by heading. An h1 should name the page. h2s should name sections. Skipping from h1 to h4 because the type scale looked nicer is a navigation hole; style the h2 with CSS instead.

A heading that is only a styled div does not appear in that jump list. “It looks like a heading” is not a heading.

Multiple h1s are confusing on a single view. Landmark regions (main, nav, aside) are the other jump list. Two <nav>s need different names (aria-label="Product" / aria-label="Footer").

Paste the header + main titles into Screen Reader Preview and read the heading list. If you cannot outline the page from that list, neither can a customer.

Buttons. Visible text is the best name. Icon-only buttons need aria-label="Close" (or similar) that matches the action. title is a weak substitute and is often ignored until hover.

Links. The name should make sense out of context. “Click here” and “read more” (repeated twelve times) fail. “Read more about DNS records” is a name.

Inputs. A placeholder is not a label. Associate <label for="id"> or use aria-labelledby. Required and invalid states should be in the accessible name or in a described-by error, not only a red border.

Custom widgets. If you set role="combobox" you also inherit a contract (arrow keys, expanded state). Wrong ARIA is worse than a native <select>.

The preview will show “button” with no name. That is the bug. Fix it before you debate color.

Alt text that describes the job of the image

Alt is for the information or action, not a narrative of pixels.

  • Linked logo: alt="DevOkk home" (destination).
  • Chart: the conclusion, or a link to a data table - not “blue bars.”
  • Decorative flourish: alt="".
  • Text in the image: the same text, or do not put the text only in the image.

Empty alt on a meaningful image is a silent hole. Missing alt may cause the filename to be read. Neither is a feature.

CSS background images are invisible to this path. If the picture is content, it should be an <img> (or inline SVG with a title).

How to preview announcement order

  1. Copy a self-contained snippet: nav, heading, form controls, primary button.
  2. Open Screen Reader Preview and paste. No account.
  3. Read the list top to bottom. Note skips, unlabeled controls, and images that speak a filename.
  4. Fix the HTML (names, headings, alts). Paste again.
  5. Run WCAG Checker for empties and contrast you missed.
  6. Before release, listen once with a real screen reader on the deployed page.

Do not paste a 40,000-node app shell and expect a useful transcript. Isolate the piece you changed.

HTML entities in visible text (&amp;) will be spoken as the character, which is what you want. Encoding advice for untrusted strings is a different article: How to Encode HTML Entities.

Why a preview is not NVDA or VoiceOver

Engines announce tables, live regions (aria-live), and virtual cursor movement differently. Verbosity settings change whether roles are spoken. Browse mode versus focus mode changes what arrows do.

A preview that looks clean can still fail when a modal does not trap focus or a live region never fires. Those need a real reader and a keyboard.

Use the preview as lint for names and order. Use a person and a real engine as the exam.

Listen to the snippet, then check names

Paste the snippet you just built into Screen Reader Preview, then run WCAG Checker on the same page. Fix names and headings before you add another animation.

Frequently asked questions

Do screen readers read the CSS layout?

They read the accessibility tree, which comes from HTML semantics, names, and ARIA - not from flex order or ‘it looks like a heading because it is 32px.’ Visual CSS does not create an h2.

Is Screen Reader Preview the same as NVDA or VoiceOver?

No. Screen Reader Preview is a teaching view of names and order for markup you paste. Real engines differ by OS, browser, and user settings. Always smoke-test with one real reader before a release that changes the header or checkout.

Why is my icon button announced as ‘button’?

It has no accessible name. Add visible text, aria-label, or aria-labelledby pointing at a label. An icon font with no text is silent on purpose.

Should decorative images have alt?

Use alt="" so they are skipped. Meaningful images need alt that states the function or the information, not ‘IMG_4021’.

Does `display: none` hide content from screen readers?

Yes, typically. visibility: hidden and hidden also remove it. opacity: 0 or off-screen position may still be announced - do not hide errors that way if you need them read.

How does this relate to WCAG?

Names, structure, and alts are WCAG perceivable/operable work. WCAG Checker flags many empties; the preview lets you hear the sequence. See A Practical WCAG Checklist.

More reading that links back to the same tools and workflows.

RoundupCSS & Frontend

Best CSS and Frontend Design Tools

Color palettes, CSS animation previews, favicons, patterns, bundle size, and screen-reader checks - all in the browser.

4 min read