Web Accessibility: banner role
Tags: web, a11y
Published: 2023-06-27 07:39:37

The `banner` role is an ARIA [landmark role](https://developer.mozilla.org/en-US/blog/aria-accessibility-html-landmark-roles/#what_are_html_landmark_roles) 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.

```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.

```yaml
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
```html
<nav>
  <header>
    <a class="logo" href="/">
      <span class="visually-hidden">Mr. Pineapple's Pizzeria</span>
    </a>
  </header>
</nav>
```

```yaml
RootWebArea "Demo App" focusable: true
    navigation: ""
        HeaderAsNonLandmark: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true
```

## inside aside

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

```yaml
RootWebArea "Demo App" focusable: true
    complimentary: ""
        HeaderAsNonLandmark: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true
```

## inside article

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

```yaml
RootWebArea "Demo App" focusable: true
    article: ""
        HeaderAsNonLandmark: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true
```

## inside section

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

```yaml
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.

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

```yaml
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?.

```html
<body>
  <div id="app">
    <header></header>
    <main></main>
    <footer></footer>
  </div>
</body>
```

```yaml
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.

```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.
```yaml
RootWebArea "Demo App" focusable: true
    Ignored: "" # <app-container>
        banner: ""
            link: "Mr. Pineapple's Pizzeria" focusable: true
```