Structure and landmark roles
Structure roles describe content that is not a control: headings, lists, tables, quotes, and the big regions of a page
(landmarks). Almost every one has an HTML element. The role attribute is the fallback when you cannot change the
element, not a second copy of the element you already used.
In one minute
- Landmarks are the big regions (header, nav, main, aside, footer). Screen reader users jump between them like a table of contents for the page layout.
- Use the HTML element:
<header>,<nav>,<main>,<aside>,<footer>. Noroleneeded. - If a page has two of the same landmark, give each a name with
aria-label. - Headings, lists and tables only work when they are real. A bold
divis not a heading.
Picture a shopping mall with no signs on the stores and no directory. You would walk every corridor. Landmarks are the directory and the signs. A sighted person scans the layout in a glance. A screen reader user gets the same shortcut from the landmark list: "jump to main", "jump to navigation". Headings are the signs inside each store.
1. From divs to landmarks
The accessibility tree is the simplified copy of your page that the browser gives to assistive technology. A
div appears there as "nothing special". A <nav> appears as a navigation region. Switch the page below
between the two and watch the landmark list.
Step 1. Pick how the page is built. Highlighted boxes are exposed as landmarks.
This is WCAG 2.4.1 Bypass Blocks and 1.3.1 Info and Relationships at work. A keyboard-only or screen reader user can skip the repeated header
and menu and land on the content. Two scoping rules trip people up. A <header> or <footer> inside
an <article>, <section>, <main> or <aside> is not the page banner or
contentinfo. It is just the header of that piece. And a page should have exactly one main.
2. Two of the same? Give each a name
If the page has a primary menu and a footer menu, the landmark list shows "navigation, navigation". Which is which? A name fixes it. Some
landmarks also need a name just to exist: a <section> or <form> without one is plain content, not a landmark.
Step 2. Toggle the names and compare the landmark list.
- Use a short name that does not repeat the role:
aria-label="Primary", not "Primary navigation navigation". aria-labelledbypointing at a visible heading is even better, because the name stays in sync with the text.- Do not add
role="navigation"to a<nav>. That is redundant noise.
3. Headings are the outline of the page
Many screen reader users press one key to list every heading on the page and then jump straight to one. The levels (h1 to h6) tell them what is inside what. Choose the heading level for meaning, then style it with CSS. Never pick a level for its font size.
Step 3. Compare an outline that skips levels with one that nests properly.
A skipped level (h1 then h3) makes a listener wonder if they missed a section. One h1 per page is the safe habit. If you must use the
role, role="heading" needs aria-level. This supports WCAG 1.3.1 and 2.4.6 Headings and Labels.
4. Meter or progress bar?
They look alike but mean different things. A progress bar tracks work that is finishing, like an upload. A meter is a
measurement inside a known range, like disk space used. The element you pick changes what is announced.
Step 4. Pick what you are showing, pick the element, and drag the value.
5. Quick check: which element?
Four short cases. Pick the element that carries the right meaning.
6. Reference: landmark roles
All landmarks inherit from the abstract landmark type. Do not use role="landmark". Use one concrete region, and name it when the page has more than one of that kind.
| banner | Site-oriented header, not the heading of one article. HTML: one <header> that is not inside an article or section. A page should expose one banner. |
|---|---|
| navigation | A group of links for moving around. HTML: <nav>. Name each one if there are two: aria-label="Primary". |
| main | The primary content. HTML: one <main>. Do not put two mains on a page. |
| complementary | Supporting content that still makes sense alone, such as a related-articles aside. HTML: <aside>. |
| contentinfo | Page footer metadata: copyright, privacy, site links. HTML: a <footer> that is scoped to the page, not to one article. |
| form | A landmark only when the form has an accessible name. An unnamed <form> is not a landmark. Name a search or filter form so it shows up in the rotor. |
| search | The search region. HTML: <search>, or a form with role="search" if you cannot use that element. |
| region | A generic landmark. It is only exposed as a landmark when it has a name. HTML: a <section> with an accessible name. Do not sprinkle unnamed regions. |
7. Reference: document structure roles
These organize content and are usually not interactive. "Name is prohibited" means aria-label on that role is ignored. The text inside is the content.
role="application" tells the screen reader to stop using its own reading keys and pass them to your page. Used on <body>, it breaks navigation for everyone. role="none" removes semantics: never put it on a focusable control or something with state.
| article | A composition that stands alone: a post, a comment’s target. HTML: <article>. |
|---|---|
| blockquote | A quotation from elsewhere. HTML: <blockquote>. Name the source in a cite, not by stuffing it into the role. |
| caption | Names a figure, table, or grid. HTML: <caption> or <figcaption>. Name is prohibited on the caption role itself. |
| cell | A cell in a static table. HTML: <td>. An interactive cell is gridcell, not cell. |
| columnheader | A column’s header cell. HTML: <th scope="col">. |
| rowheader | A row’s header cell. HTML: <th scope="row">. |
| row | A row in a table, grid, or treegrid. HTML: <tr>. |
| rowgroup | A group of rows: header, body, or footer. HTML: thead, tbody, tfoot. |
| table | Static data in two dimensions. HTML: <table>. Do not use this role on a CSS grid of cards. |
| list | A list of items. HTML: ul or ol. |
| listitem | One item. HTML: <li>. A listitem whose parent is not a list is a broken tree. |
| definition | A definition of a term. HTML: <dd> inside a <dl>. |
| term | The phrase being defined. HTML: <dfn> or <dt>. Name is prohibited. |
| heading | A heading with a level. HTML: h1–h6. If you must use the role, set aria-level. Do not skip levels to chase a font size. |
| paragraph | A paragraph of text. HTML: <p>. Name is prohibited. |
| figure | Self-contained content, often with a caption. HTML: <figure>. |
| image | An image. Synonym: img. HTML: <img alt>. The name is required and is the alternative text. Empty alt is a decorative image, which should not be a named image role. |
| math | A mathematical expression. Prefer MathML. The role is the fallback, and the name should be a spoken form of the expression. |
| meter | A scalar measurement inside a known range, such as a disk quota. HTML: <meter>. Not a progress bar. Progress is work completing. Meter is a measurement. |
| group | A set of related interface objects that is not a landmark. HTML: <fieldset> or a <div role="group" aria-labelledby> when you need a name and fieldset is wrong. |
| toolbar | Also listed as a widget container. As structure it groups controls. Keyboard behavior is what makes it a widget. See lesson 18. |
| separator | When not focusable, a thematic break. HTML: <hr>. |
| document | A region treated as document reading mode inside an application. You almost never set this. The page itself is already a document. |
| application | A region where the author handles keys that screen readers normally use for reading. This mode disables a lot of assistive-tech shortcuts. Use it only around a widget that truly needs those keys, not on <body>. |
| feed | A stream of articles that may load as you move. Each child should be an article. Infinite scroll that is only a list does not need this role. |
| directory | A list of references, like a table of contents. Often a list is clearer. The role is legacy. Prefer a named navigation or a list. |
| note | Content that is parenthetic or ancillary to the main point. Do not use it for a warning people must read. A warning should be text in the flow, or an alert if it is urgent. |
| comment | A reaction to other content. ARIA 1.3 adds this so a comment can be found as a comment, not just another article. The comment still needs text. The role does not thread replies for you. |
| suggestion | Proposed content, such as an edit suggestion. Name is prohibited. The text of the suggestion is the content. Pair it with insertion and deletion when you are showing a change. |
| insertion | Content added in a change. HTML: <ins>. Name is prohibited. |
| deletion | Content removed in a change. HTML: <del>. Name is prohibited. |
| mark | Highlighted content for reference, not emphasis. HTML: <mark>. Name is prohibited. |
| emphasis | Stress emphasis. HTML: <em>. Name is prohibited. Do not use it to paint italics. |
| strong | Strong importance. HTML: <strong>. Name is prohibited. |
| code | A fragment of computer code. HTML: <code>. Name is prohibited. |
| time | A time or date. HTML: <time datetime>. Name is prohibited. The datetime attribute is the machine value. |
| subscript | Subscript that changes meaning, not a styling trick. HTML: <sub>. |
| superscript | Superscript that changes meaning. HTML: <sup>. |
| sectionheader | A header inside a section, card, or landmark, when it is not the page banner. Do not use banner for every card header. |
| sectionfooter | A footer inside a section or card, when it is not the page contentinfo. |
| generic | An element with no semantics, like a <div> or <span>. You do not set this role to “help.” Name is prohibited. The point of the role is the absence of a role. |
| none | Same as presentation. Removes the element’s implicit role from the tree and flattens it. Use it to fix a layout table or a list that is only visual. Never on a focusable control, an element with a name you need, or anything with a state. |
| tooltip | A popup description of an element. Name is prohibited because the tooltip’s content is the description. The control it describes should point at it with aria-describedby. Hover-only tooltips fail keyboard and touch. If the text matters, put it in the page. |
Common mistakes
| You see | Why it is a problem | Fix |
|---|---|---|
Page of <div>s only | No landmarks to jump between. | header, nav, main, aside, footer. |
Two <nav>s, no names | Landmark list says "navigation" twice. | aria-label on each. |
Unnamed <section> expected to be a region | It is not exposed as a landmark. | Add a name, or use a heading and no role. |
| Heading chosen for font size | Outline is wrong or skips levels. | Pick the level by meaning, style with CSS. |
CSS grid of cards with role="table" | Announces row and column counts that do not exist. | Use a list. |
Hover-only tooltip | Keyboard and touch users never see it. | Put the text on the page, link with aria-describedby. |
- Open the accessibility tree in your browser's dev tools and list the landmarks on this lesson. You should find a navigation and a main, both from HTML elements.
- Turn on a screen reader and open its landmark or headings list (VoiceOver rotor, NVDA elements list).
Remember
- Landmarks come from HTML elements. Name duplicates.
- An unnamed
sectionorformis not a landmark. - Headings: one h1, no skipped levels, pick by meaning.
- Use
meterfor a measurement andprogressfor work finishing. - Roles with "name prohibited" take their name from their content only.