skip to content

Does an HTML <header> element always expose the banner landmark role? What decides whether <header> and <footer> become banner and contentinfo?

level: seniorimportance: should knowfreq 38%

answer

  1. the role depends on the ancestor
  2. nested inside sectioning content changes it
  3. fifty articles would mean fifty banners
  4. a layout wrapper can silently remove it
  5. check the computed role, not the markup

basics

~10 s
<header> and <footer> expose the banner and contentinfo landmark roles only when they are not nested inside <article>, <aside>, <main>, <nav> or <section>. Nested ones are generic: still meaningful markup, but not landmarks.

solid answer

~50 s

No — the role depends on where the element sits. A `<header>` whose nearest sectioning ancestor is the document body maps to the `banner` landmark, and the matching `<footer>` maps to `contentinfo`. Put either one inside `<article>`, `<aside>`, `<main>`, `<nav>` or `<section>` and it maps to generic instead: it is still the correct element for a post's byline block or a card's meta row, but it does not appear in the landmark list. That is deliberate — a feed of fifty articles, each with a `<header>`, would otherwise produce fifty banner landmarks, and banner is meant to be the page's one masthead. The practical consequences are that you get the page-level landmarks for free without writing `role=`, and that if an audit reports a missing banner or contentinfo, the usual cause is a header or footer that has drifted inside a wrapper such as `<main>`.

code

html · 20 lines
html
<body>
  <header>
    <a href="/">Acme</a>
  </header>

  <main>
    <article>
      <header>
        <h2>Release notes 4.2</h2>
        <p><time datetime="2026-03-12">12 March 2026</time></p>
      </header>
      <p>Bug fixes and one new export format.</p>
      <footer><p>Filed under: releases</p></footer>
    </article>
  </main>

  <footer>
    <p>&copy; 2026 Acme</p>
  </footer>
</body>

go deeper

for a junior

Know that <header> and <footer> can be used both at page level and inside an article or card, and that only the page-level ones are landmarks.

for a middle

Name the exact condition: not a descendant of article, aside, main, nav or section. Be able to point at a nested header and say what role it actually computes to.

for a senior

Treat this as a regression you can catch. Explain how a layout wrapper silently removes banner and contentinfo, and show that you would verify against the computed accessibility tree rather than reading the source.

for a principal

Own it structurally — the app shell, not feature pages, should place the page-level header and footer, so a component author cannot accidentally nest or duplicate them across the product.

## The mapping is contextual, not fixed Most HTML elements map to one ARIA role no matter where they appear. `<header>` and `<footer>` do not. Their role in the accessibility tree is computed from their ancestry: - `<header>` → `banner`, and `<footer>` → `contentinfo`, when the element is **not** a descendant of `<article>`, `<aside>`, `<main>`, `<nav>` or `<section>` (nor of an element carrying the equivalent explicit roles). - Otherwise → generic. No landmark, no rotor entry. So the same element, unchanged, is a landmark in one position and not in another: ```html <body> <header> <!-- role: banner --> <a href="/">Acme</a> </header> <main> <article> <header> <!-- role: generic, NOT banner --> <h2>Release notes 4.2</h2> <p>Posted 12 March</p> </header> <p>…</p> <footer> <!-- role: generic, NOT contentinfo --> <p>Filed under: releases</p> </footer> </article> </main> <footer> <!-- role: contentinfo --> <p>© 2026 Acme</p> </footer> </body> ``` ## Why the spec works this way `banner` means "this is the site's masthead" and `contentinfo` means "this is the page's footer information" — both are page-level claims, and both are expected to appear roughly once. But `<header>` and `<footer>` are also the right elements for *component-level* furniture: an article's byline block, a card's meta row, a `<section>`'s intro. Without the scoping rule, a feed of fifty posts would emit fifty banner landmarks and the landmark list would become unusable. Making the role conditional lets one element serve both jobs — page masthead and component header — without the author having to intervene. This is also a neat illustration of why "just add `role=banner` to be explicit" is bad advice: it overrides the context-aware mapping with a fixed one, which is exactly what you do not want on a nested header. ## The bug this causes in real code The common regression is a layout refactor that moves the site header inside a wrapper. If a framework's shell renders ```html <main> <header>…site masthead…</header> …page content… </main> ``` the masthead silently stops being a banner landmark. Nothing looks different; the page still renders identically; only the landmark list changed. The same happens when a developer wraps the whole page in `<section class="page">` for styling — every top-level header and footer inside it loses its landmark role at once. The reverse mistake also happens: a footer meant to be the article's is left as a sibling of `<main>`, and now the page reports contentinfo content that actually belongs to one article. ## How to check it rather than reason about it Do not eyeball the ancestry; read the accessibility tree. Browser devtools expose the computed role for a selected node, and an accessibility-tree or landmarks view will list what the page actually exposes. Automated checks also flag well-known landmark problems — duplicate banners, content sitting outside every landmark — but the fastest confirmation is to look at the computed role of the header itself and see whether it says `banner` or `generic`. ## Adjacent facts worth knowing A page is expected to have at most one banner and one contentinfo. Duplicates are not a parse error, but they defeat the purpose, and audits routinely flag them. `<header>` and `<footer>` have a content restriction of their own: neither may contain another `<header>` or `<footer>`, and neither may contain `<main>`. That is a separate rule from the role mapping, but it comes from the same idea — these are furniture wrappers, not general-purpose containers. Finally, `<footer>` is not required to be last, and `<header>` is not required to be first. They are defined by their role in the content, not their position, so a byline `<header>` can legitimately appear after an image, and a footer's contents are "information about its section" rather than "the bottom of it".

  • A team wraps the whole page in <section class="app-shell"> for styling. What happens to the landmarks?
    The top-level `<header>` and `<footer>` are now descendants of sectioning content, so they drop from `banner` and `contentinfo` to generic and vanish from the landmark list. Nothing changes visually, which is what makes it dangerous. The fix is to use a `<div>` for the styling wrapper — it carries no sectioning semantics and leaves the mapping intact.
  • Should you add role="banner" to a header to be explicit?
    No. On a top-level header it is redundant, and on a nested one it is actively wrong — it forces a page-level landmark onto component furniture and undoes the context-sensitivity the spec built in. If you want a banner, place the header at the top level; if you do not, leave the element alone.
  • Can a <header> contain another <header>?
    No. `<header>` and `<footer>` may not contain another `<header>` or `<footer>`, and neither may contain `<main>`. They are furniture wrappers for the section they introduce or conclude, not general-purpose containers, so a nested pair is invalid regardless of what role either one would have mapped to.

saying these in an interview costs you the question

  • Assuming <header> is always the banner landmark
  • Adding role="banner" to an article's header
  • Believing <footer> must be the last element on the page
  • Using <section> as a page wrapper and losing landmarks
  • Thinking a nested <header> is wrong markup rather than non-landmark

context