skip to content

A screen reader user reports that a page is hard to navigate: its only <h1> is the site logo and every section title is a styled <div>. How do such users normally move through a page by heading, and what specifically breaks here?

level: seniorimportance: should knowfreq 44%

answer

  1. headings are an index, not decoration
  2. H key and the headings list
  3. brand at the top helps nobody
  4. styled div never enters the list
  5. skimmable degrades to linear

basics

~20 s

Screen reader users jump heading to heading with a shortcut key or pull up a headings list to skim a page. A logo as h1 makes every page's top entry identical, and styled divs never enter the list at all, so the page reads as one undifferentiated block.

solid answer

~60 s

Screen readers expose headings as a navigable index: in browse mode, `H` moves to the next heading, the number keys move to the next heading of a given rank, and a dedicated list dialog or rotor shows all headings with their levels so a user can skim the page the way a sighted user skims subheads. That index is built purely from `h1`–`h6` in the accessibility tree. Here it fails twice. The `h1` is the site name, so the top of every page's list is identical and nothing tells the user what *this* page is. And the section titles are `div`s, which carry no heading semantics, so they simply are not in the list — the user sees an almost empty index for a page that visually has clear structure, and has to fall back on reading linearly or hunting with find. The fix is markup: make the `h1` the page's own subject, put the logo in a link with an image, and promote the visual section titles to real `h2`/`h3` elements.

go deeper

for a junior

Know that screen reader users jump between headings rather than reading everything, and that only real h1-h6 elements appear in that list.

for a middle

Explain the mechanics — the H key, rank keys, and the headings list or rotor — and why a styled div is invisible to all three despite looking identical on screen.

for a senior

Diagnose a real page: read the heading sequence alone, judge whether it is a usable table of contents, and know that tooling catches skipped levels but never catches an unhelpful h1 or a div in disguise.

for a principal

Frame headings as a navigation contract the product owes a class of users, and make sure design reviews and component APIs cannot quietly delete it in the name of visual fidelity.

## How heading navigation actually works A screen reader in browse mode (NVDA and JAWS on Windows) or with the rotor (VoiceOver on macOS and iOS) treats the page as a document you can index into. For headings that means three interaction patterns: - **Next/previous heading.** Pressing `H` moves to the next heading, `Shift+H` to the previous one. This is the workhorse: users tab-tab-tab through a page's structure the way a sighted reader's eye jumps down the subheads. - **Next heading of a specific rank.** The number keys `1`–`6` move to the next `h1`…`h6`. "Give me the next top-level section" is `2` on a well-structured page. - **A list of all headings.** NVDA's Elements List (`Insert+F7`), JAWS's headings list (`Insert+F6`), and the VoiceOver rotor (`VO+U`, then the Headings menu) all render the page's headings as a flat list with their levels. This is the closest thing to seeing the page at a glance, and surveys of screen reader users consistently report it as one of the first things they reach for on an unfamiliar page. Everything in those three mechanisms is fed by one thing: elements exposed to the accessibility tree with a heading role and a level. Native `h1`–`h6` do that automatically. ## Failure one: the logo as h1 When the `h1` is the site name, every page in the site starts its heading list with the same words. The user's first question on landing — "what is this page?" — goes unanswered by the mechanism designed to answer it. Worse, the page's actual subject, if it is marked up at all, appears as an `h2` sitting under a site-wide banner, so the outline claims the page's topic is a subsection of the brand. The correction is small. The site name belongs in the banner as a link containing the logo image; it does not need to be a heading at all. The `h1` becomes the page's own subject — usually close in wording to the document `<title>`, since both answer "what page am I on". ```html <!-- before: brand claims the top of every page's outline --> <h1><img src="/logo.svg" alt="Northwind"></h1> <h2>Order history</h2> <!-- after: the page names itself --> <a href="/"><img src="/logo.svg" alt="Northwind"></a> <h1>Order history</h1> ``` ## Failure two: section titles that are not headings A `<div class="section-title">` styled at 24px and bold looks exactly like a heading and is exactly not one. It has no heading role, so: - `H` skips it — the user presses `H` and lands three screens further down, or hears "no more headings". - It is absent from the headings list, so the page's index is far shorter than its visible structure. - The rank information a user relies on to understand nesting simply does not exist for that content. The practical effect is that the page degrades from skimmable to linear. A sighted user reads five subheads in two seconds and jumps to the relevant one; the screen reader user reads, or arrows through, the entire body. On a long page that is the difference between a ten-second task and a two-minute one. ## How to diagnose this on a real page The fastest check that requires no assistive technology: extract the heading elements in order and read them as a list. In a browser console you can dump them, or use any outline-viewing extension — the point is to look at *only* the headings and ask whether that list is a usable table of contents for the page. Two questions decide it: 1. **Does the first entry name this page?** If it names the site, or names a navigation region, the `h1` is wrong. 2. **Is every visually-obvious section title in the list, at a level that matches its nesting?** Anything you can see on screen but cannot find in the list is a `div` pretending. Automated tooling helps with part of this — axe-core's `heading-order` rule catches skipped levels — but no automated rule can tell you that a heading's *text* is unhelpful or that a styled `div` should have been a heading. That judgment is the part interviewers are testing. ## The senior framing The deeper point is that heading markup is not decoration or an SEO chore: it is the page's navigation API for a whole class of users. When you delete a heading element because the design "doesn't have a title there", or wrap a title in a `div` because a heading tag brought unwanted default styles, you are removing a navigation affordance, not a style. Both of those are solvable in CSS without touching the element; neither is a reason to change the markup.

  • The design has a section with no visible title. Do you add a hidden heading?
    Often yes. A visually-hidden heading keeps the outline complete for heading navigation while leaving the design untouched — it is a legitimate technique, not a hack. Use it sparingly and honestly: the hidden text must describe the section a sighted user infers from layout, not repeat a nearby label or stuff keywords.
  • A heading tag brings default margins and sizes the designer does not want. Is that a reason to use a div?
    No. Default styling is entirely overridable in CSS, and the semantics are not recoverable once you drop the element. Style the heading to match the design; if a team keeps hitting this, the fix is a reset or a utility class, not markup that removes a navigation affordance.
  • Beyond the h1, what makes heading text itself good or bad for this kind of navigation?
    It has to work out of context, because the user often reads it in a flat list with no surrounding content. "Overview", "More", and "Details" repeated four times are useless there. Headings that name their own content — "Refund window", "Delivery estimates" — turn the list into a real table of contents.

saying these in an interview costs you the question

  • Assumes screen readers only read pages top to bottom
  • Says a bold styled div is announced as a heading
  • Puts the site logo in the h1 on every page
  • Removes headings because the design shows no visible title
  • Treats heading markup as an SEO concern only

context