Lesson 19 · Part 4 · Structure roles

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

In plain words

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.

Landmarks a screen reader user can jump to:
    Choose a version.

    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.

    
              
    Landmark list:
      Toggle to compare.

      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.

        Toggle to compare.

        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.

        
                  
        Pick a combination.

        5. Quick check: which element?

        Four short cases. Pick the element that carries the right meaning.

        Choose an answer.

        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.

        bannerSite-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.
        navigationA group of links for moving around. HTML: <nav>. Name each one if there are two: aria-label="Primary".
        mainThe primary content. HTML: one <main>. Do not put two mains on a page.
        complementarySupporting content that still makes sense alone, such as a related-articles aside. HTML: <aside>.
        contentinfoPage footer metadata: copyright, privacy, site links. HTML: a <footer> that is scoped to the page, not to one article.
        formA 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.
        searchThe search region. HTML: <search>, or a form with role="search" if you cannot use that element.
        regionA 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.

        Be careful with application and none

        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.

        articleA composition that stands alone: a post, a comment’s target. HTML: <article>.
        blockquoteA quotation from elsewhere. HTML: <blockquote>. Name the source in a cite, not by stuffing it into the role.
        captionNames a figure, table, or grid. HTML: <caption> or <figcaption>. Name is prohibited on the caption role itself.
        cellA cell in a static table. HTML: <td>. An interactive cell is gridcell, not cell.
        columnheaderA column’s header cell. HTML: <th scope="col">.
        rowheaderA row’s header cell. HTML: <th scope="row">.
        rowA row in a table, grid, or treegrid. HTML: <tr>.
        rowgroupA group of rows: header, body, or footer. HTML: thead, tbody, tfoot.
        tableStatic data in two dimensions. HTML: <table>. Do not use this role on a CSS grid of cards.
        listA list of items. HTML: ul or ol.
        listitemOne item. HTML: <li>. A listitem whose parent is not a list is a broken tree.
        definitionA definition of a term. HTML: <dd> inside a <dl>.
        termThe phrase being defined. HTML: <dfn> or <dt>. Name is prohibited.
        headingA 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.
        paragraphA paragraph of text. HTML: <p>. Name is prohibited.
        figureSelf-contained content, often with a caption. HTML: <figure>.
        imageAn 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.
        mathA mathematical expression. Prefer MathML. The role is the fallback, and the name should be a spoken form of the expression.
        meterA 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.
        groupA 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.
        toolbarAlso listed as a widget container. As structure it groups controls. Keyboard behavior is what makes it a widget. See lesson 18.
        separatorWhen not focusable, a thematic break. HTML: <hr>.
        documentA region treated as document reading mode inside an application. You almost never set this. The page itself is already a document.
        applicationA 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>.
        feedA 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.
        directoryA list of references, like a table of contents. Often a list is clearer. The role is legacy. Prefer a named navigation or a list.
        noteContent 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.
        commentA 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.
        suggestionProposed 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.
        insertionContent added in a change. HTML: <ins>. Name is prohibited.
        deletionContent removed in a change. HTML: <del>. Name is prohibited.
        markHighlighted content for reference, not emphasis. HTML: <mark>. Name is prohibited.
        emphasisStress emphasis. HTML: <em>. Name is prohibited. Do not use it to paint italics.
        strongStrong importance. HTML: <strong>. Name is prohibited.
        codeA fragment of computer code. HTML: <code>. Name is prohibited.
        timeA time or date. HTML: <time datetime>. Name is prohibited. The datetime attribute is the machine value.
        subscriptSubscript that changes meaning, not a styling trick. HTML: <sub>.
        superscriptSuperscript that changes meaning. HTML: <sup>.
        sectionheaderA header inside a section, card, or landmark, when it is not the page banner. Do not use banner for every card header.
        sectionfooterA footer inside a section or card, when it is not the page contentinfo.
        genericAn 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.
        noneSame 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.
        tooltipA 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 seeWhy it is a problemFix
        Page of <div>s onlyNo landmarks to jump between.header, nav, main, aside, footer.
        Two <nav>s, no namesLandmark list says "navigation" twice.aria-label on each.
        Unnamed <section> expected to be a regionIt is not exposed as a landmark.Add a name, or use a heading and no role.
        Heading chosen for font sizeOutline 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 tooltipKeyboard and touch users never see it.Put the text on the page, link with aria-describedby.
        Try it yourself
        1. 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.
        2. Turn on a screen reader and open its landmark or headings list (VoiceOver rotor, NVDA elements list).

        Remember

        Edit this example in the playground