Stockio

Semantic HTML Landmarks: header, nav, main and footer

Give page regions clear meaning with native HTML elements, distinguish landmarks from articles, and verify navigation without adding redundant ARIA roles.

By Jonah Weiss

Design Systems Lead ·

On this page

A page can look organized while exposing almost no useful structure to assistive technology. Replacing a few generic wrappers with meaningful HTML helps users understand the page and navigate its major regions. The important step is choosing elements by purpose rather than by their visual position or the CSS classes they happen to carry.

Map the page before choosing elements

Start with a plain-language outline: site identity, primary navigation, unique page content, related information, and site-wide details. This exercise separates document structure from layout. A sidebar can contain primary content, while a horizontal strip can contain complementary content; position alone does not decide the semantics.

When documenting markup in a tutorial or an interface that displays source, use the HTML entity encoder to encode angle brackets before placing the example into HTML text. It helps show the tags literally. It is not a sanitizer for accepting arbitrary HTML, and it does not replace contextual escaping in application templates.

Review the WAI landmark regions guidance alongside your outline. Native elements often supply the right roles automatically, but not every semantic element is a landmark. In particular, article identifies a self-contained composition; it does not create the same navigation landmark as main or nav.

Give the document a clear primary structure

Use one visible main for the dominant content of the current document. Persistent navigation, a site-wide masthead, and global footer details normally belong outside it. If your application keeps inactive views in the DOM, ensure their main elements are properly hidden rather than exposing multiple competing primary regions.

A top-level header usually exposes a banner landmark, and a top-level footer usually exposes contentinfo. Their meaning changes with context: a header or footer inside an article or section describes that local section instead of creating another site banner or contentinfo landmark. Do not assign redundant roles to native elements unless a specific compatibility requirement justifies it.

<a href="#content">Skip to content</a>
<header>
<a href="/">Example Studio</a>
<nav aria-label="Primary">
  <a href="/work">Work</a>
  <a href="/about">About</a>
</nav>
</header>
<main id="content">
<h1>Studio journal</h1>
<p>Notes from our latest projects.</p>
</main>
<footer>
<p>Example Studio contact information</p>
</footer>

The skip link targets a stable identifier on main. Its visibility and focus behavior still need testing; semantic markup does not automatically make a hidden skip link usable. Give the page a descriptive title and heading as well. Landmarks and headings are complementary navigation systems, not substitutes for one another.

The MDN main reference explains the element's intended scope. Keep route-specific content inside main when building client-rendered applications, even if the surrounding shell never reloads.

Use nav for significant navigation groups

The nav element identifies a major group of navigation links. Primary navigation, a table of contents, and pagination can qualify. A handful of incidental links in a paragraph or a footer does not automatically need its own nav wrapper. Overusing landmarks makes the navigation list harder to scan.

When several navigation regions serve different purposes, give them distinct accessible names. Use aria-label for a concise name when there is no visible heading, or aria-labelledby when an existing heading names the region. Avoid unnecessary words such as navigation in the label because assistive technology already communicates the role.

<nav aria-labelledby="contents-title">
<h2 id="contents-title">On this page</h2>
<ul>
  <li><a href="#setup">Setup</a></li>
  <li><a href="#examples">Examples</a></li>
</ul>
</nav>

If two navigation regions contain the same links for the same purpose, matching labels can communicate that equivalence. Do not invent different names merely to make every string unique. Keep link text meaningful outside its surrounding visual treatment, and retain lists when the links form a logical collection.

For a wider implementation checklist, consult the existing accessible interfaces guide. It connects structural decisions with keyboard behavior and interaction details that landmarks alone cannot solve.

Distinguish articles, sections, and complementary content

An article element fits content that could reasonably stand alone: a news story, a forum post, a product review, or an independently reusable card. It can have its own header and footer. Those local wrappers describe the article's introduction and closing details, not the entire page.

Use section for a thematic grouping when a more specific element is not appropriate, usually with a heading. Use div when you only need a styling or scripting wrapper. Replacing every div with section creates implied organization without necessarily providing useful meaning.

An aside element contains material indirectly related to its surrounding content. A glossary callout within a tutorial or related reading beside an article can fit. A checkout summary essential to completing a purchase may be part of the main task instead, despite appearing in a sidebar.

<article aria-labelledby="post-title">
<header>
  <h2 id="post-title">Designing a useful empty state</h2>
  <p>Published by the product team</p>
</header>
<p>The article's self-contained content goes here.</p>
<aside aria-label="Related terminology">
  <p>An empty state explains what can happen next.</p>
</aside>
<footer>
  <p>Filed under interface patterns</p>
</footer>
</article>

Choose headings deliberately rather than assuming sectioning elements automatically calculate an accessible heading hierarchy. Use h1 through h6 according to the actual document structure. The WHATWG sections specification provides the normative definitions when an edge case is unclear.

Verify the accessibility tree and reading order

Inspect the browser's accessibility tree, not just the DOM. Check the roles and names actually exposed for banner, navigation, main, complementary, and contentinfo. A missing name on one of several similar regions is often easier to notice here than in a visual review.

Next, navigate the page with a keyboard and a screen reader's landmark and heading shortcuts. Confirm that the sequence matches the intended reading order. CSS grid placement and flex ordering can visually rearrange elements without changing their DOM order, creating a mismatch between what sighted and nonvisual users encounter.

Try a representative content page, a search results page, and an error state. Templates sometimes preserve the happy path but render duplicate main elements during loading or leave a route without a heading after an error. Include these states in a reusable layout test plan.

Keep semantic review separate from visual polish. Browse development resources for implementation work, and use the HTML and CSS collection for related layout guidance. A small, accurate set of landmarks is more useful than a large set of decorative wrappers with impressive names.

Key takeaways

  • Choose elements by content purpose, not their visual location.
  • Keep primary content in one visible main region.
  • Name multiple navigation regions according to their purpose.
  • Article is semantic structure, not a navigation landmark.
  • Check exposed roles, heading order, and keyboard behavior in real page states.
Featured sponsor

Reach designers & developers at work

Put your product next to the tools people use every day. One sponsor per placement, no tracking pixels.

Become a sponsor

Keep reading

Related articles

More in HTML & CSS
HTML & CSS

10 Best HTML Email Template Resources

Find ten reliable starting points for HTML email layouts, from visual builders and coded templates to tested frameworks, plus guidance on accessibility and inbox checks.

Includes: HTML entitiesMarcus BellMarcus Bell
HTML & CSS

15 Best Free Resources to Learn HTML and CSS

Start learning HTML and CSS with fifteen respected free tutorials, interactive exercises, and reference sites, then choose a next step that suits your schedule and goals.

Includes: HTML entitiesJonah WeissJonah Weiss
Accessibility

8 Best Accessible UI Component Libraries

Find an accessible component library for React, Vue, or Bootstrap projects, with practical notes on keyboard behaviour, styling freedom, and what your team must still test itself.

Includes: HTML entitiesNoor HaddadNoor Haddad
Accessibility

8 Best Screen Readers for Testing Your Website

Compare eight screen readers across Windows, Apple, Android, and ChromeOS, with concrete keyboard and browser pairings plus practical checks for forms, headings, focus, and dynamic updates.

Includes: HTML entitiesTheo OkaforTheo Okafor
Backend & APIs

How to Prevent XSS Attacks in Web Forms

Protect form data from XSS with context-aware output handling, safe DOM APIs, URL validation, and practical tests for previews, saved content, and errors.

Includes: HTML entitiesChidi NwosuChidi Nwosu
JavaScript & Frameworks

Event Delegation in JavaScript: DOM Event Patterns

Build resilient DOM interactions with delegated listeners, clear event ownership, safe target matching, and lifecycle cleanup for dynamically changing interfaces.

Includes: HTML entitiesDaniel KimDaniel Kim