Web Accessibility: banner role

The banner role is an ARIA landmark role that is used to identify the header of a webpage. This section of the page typically contains information such as the website’s logo, navigation menu, and search input.

By using the the banner role, assistive technologies can quickly identify and navigate to this important section of the page, improving the accessibility and usability of the website for users with disabilities, as well as improve the semantics of the HTML and making it easier to style.

index.html
<body>
  <header>
    <a class="logo" href="/">
      <span class="visually-hidden">Mr. Pineapple's Pizzeria</span>
    </a>
  </header>
</body>

When inspecting a webpage with content like above using the Chrome DevTools, the Accessibility Tree will display the banner role for the <header> element. This indicates that the <header> element has been marked with the banner ARIA landmark role, which is used to identify the header section of the webpage.

Accessibility Tree
RootWebArea "Demo App" focusable: true
    banner: ""
        link: "Mr. Pineapple's Pizzeria" focusable: true

According to the MDN documentation, the <header> element is assigned the banner role when it is not used as a child of the <main> element or another sectioning element.

sectioning element means if the <header> element is used as a child of an element such as <main>, <nav>, <aside>, <article>, or <section>, it will not be assigned the banner role. Instead, it will be assigned the HeaderAsNonLandmark role. This role is used to indicate that the <header> element is still a header, but it does not represent a landmark region of the page.

inside nav

index.html
<nav>
  <header>
    <a class="logo" href="/">
      <span class="visually-hidden">Mr. Pineapple's Pizzeria</span>
    </a>
  </header>
</nav>
Accessibility Tree
RootWebArea "Demo App" focusable: true
    navigation: ""
        HeaderAsNonLandmark: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true

inside aside

index.html
<aside>
  <header>
    <a class="logo" href="/">
      <span class="visually-hidden">Mr. Pineapple's Pizzeria</span>
    </a>
  </header>
</aside>
Accessibility Tree
RootWebArea "Demo App" focusable: true
    complimentary: ""
        HeaderAsNonLandmark: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true

inside article

index.html
<article>
  <header>
    <a class="logo" href="/">
      <span class="visually-hidden">Mr. Pineapple's Pizzeria</span>
    </a>
  </header>
</article>
Accessibility Tree
RootWebArea "Demo App" focusable: true
    article: ""
        HeaderAsNonLandmark: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true

inside section

index.html
<section>
  <header>
    <a class="logo" href="/">
      <span class="visually-hidden">Mr. Pineapple's Pizzeria</span>
    </a>
  </header>
</section>
Accessibility Tree
RootWebArea "Demo App" focusable: true
    Section: ""
        HeaderAsNonLandmark: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true

Many UI frameworks, such as React and Vue, render their contents inside a <div id="app"> tag as a direct child of the document body.

Since <div> is not a sectioning element, <header> here still gets a banner role.

index.html
<body>
  <div id="app">
    <header>
      <a class="logo" href="/">
        <span class="visually-hidden">Mr. Pineapple's Pizzeria</span>
      </a>
    </header>
  </div>
</body>
Accessibility Tree
RootWebArea "Demo App" focusable: true
    generic: "" # our div element
        banner: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true

To ensure that the webpage is accessible and follows best practices, it is recommended to follow a structure like this?.

index.html
<body>
  <div id="app">
    <header></header>
    <main></main>
    <footer></footer>
  </div>
</body>
Accessibility Tree
RootWebArea "Demo App" focusable: true
    generic: "" # our div element
        banner: ""
        main: ""
        contentinfo: ""

What if header is inside a custom element?

Let’s say we’ll put <header> inside the shadowRoot of a custom element <my-app> and see what role we get.

index.html
<body>
  <app-container>
    #shadow-root (open)
      <header>
        <a class="logo" href="/">
          <span class="visually-hidden">Mr. Pineapple's Pizzeria</span>
        </a>
      </header>
  </app-container>
</body>

Yay, we still get a accessible banner role.

Accessibility Tree
RootWebArea "Demo App" focusable: true
    Ignored: "" # <app-container>
        banner: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true