Structuring pages with semantic HTML
Landmarks are how a screen reader user jumps around a page. Headings are how they scan it. Both have to match the visual page, in source order.
In one minute
- Use
<header>,<nav>,<main>and<footer>instead of anonymous<div>s. They become landmarks. - One
<main>per page. If you have two<nav>s, give each a name witharia-label. - Headings form an outline: one
h1, thenh2,h3... without skipping levels. Size is CSS. Rank is structure. - Source order is what keyboard and screen reader users get. Never fix order with a positive
tabindex.
Landmarks are the signs on the doors of a building: Entrance, Reception, Main hall, Exit. Headings are the titles on the pages of a book's contents. A sighted visitor glances and sees both. A screen reader user cannot glance, so they ask the browser "list the doors" or "list the titles", and your markup is the only source of the answer.
1. Landmarks: one main, labelled navs, named forms
A landmark is a big labelled area of the page. Screen readers have a shortcut to list them (often called the "rotor" or "elements list") and jump straight to one,
so a user can skip the menu and land on the content. <header>, <nav>, <main> and <footer> create landmarks.
Note: <header> and <footer> are only page-level landmarks (banner, contentinfo) when they are not inside an article, section or similar.
Step 1. Build the page two ways and see which landmarks a screen reader can list.
Landmark list a screen reader offers
- Two
<nav>s without names are both announced as "navigation". Users cannot tell them apart. Usearia-label="Primary"andaria-label="Footer". - A search or filter
<form aria-label="Filter">becomes a form landmark. A form with no name is not a landmark. - Search specifically can use
<search>(newer HTML) orrole="search".
2. Do not paint the page with regions
role="region" (and <section>) only becomes a landmark when it has an accessible name. Too many landmarks is noise: the list that was supposed to help becomes forty items long.
Use a region when the area has a purpose users may want to jump to, and give it a name that says what it is.
Step 1. Add regions to the page and watch the landmark count.
3. Heading outline: rank, not size
Start at h1. Do not jump from h2 to h4 because the design wants smaller text. Size is CSS. Rank is structure.
One h1 per page is the simple rule. Many screen reader users open the headings list first, so a missing level
sounds like a missing chapter (WCAG 1.3.1, 2.4.6, 2.4.10).
Step 1. Set the level for each heading of a shop page. The outline updates.
Outline a screen reader user sees
4. Source order: layout can move boxes, not reading order
If CSS grid paints the sidebar first but the HTML puts main content first, keyboard and screen reader users get the content first.
That is usually what you want. The danger is the reverse: a visual order that differs from the source makes focus jump around.
Do not "fix" order with a positive tabindex. It builds a second tab order that is easy to break.
Step 1. Choose whether CSS swaps the two columns. Then press Tab through the links.
Focus order: (press Tab)
Common mistakes
| You see | Why it is a problem | Fix |
|---|---|---|
Page built from <div>s only | No landmarks, no headings to jump to. | Use header, nav, main, footer and real headings. |
Two unnamed <nav>s | Both read "navigation". | aria-label on each. |
More than one <main> | Unclear where the content starts. | One visible main. |
Bold <div> that looks like a heading | Not in the headings list. | Use h2, style with CSS. |
h2 then h4 for smaller text | A gap in the outline. | Use h3 and resize with CSS. |
Positive tabindex to fix order | Creates a second tab order. | Fix the HTML order. |
- In browser devtools, open the accessibility tree for this page. Find a navigation landmark named "Curriculum" and one main landmark.
- With a screen reader on, open the headings list. Does it read like a table of contents?
- Press Tab from the top of any page. Does the first stop make sense?
Remember
- Landmarks: header, nav, main, footer. Name any that repeat.
- Headings: one h1, no skipped levels, CSS for size.
- Regions need names and a reason.
- Source order is reading order. No positive tabindex.