Boost React Accessibility with Landmarks in Minutes

A blue robot with the React logo standing on a path of labeled blocks: Header, Main, Nav, Aside, Footer, leading toward a glowing accessibility icon.

As your app grows, semantics and accessibility shift from being nice-to-have to fundamental aspects of a quality user experience. Correct use of landmarks and regions helps screen-reader users, improves navigation, and makes your React app more robust and easier for search engines to understand.

What are Landmarks

Landmarks are areas of a page that help assistive technologies, like screen readers, understand the structure quickly. They provide a clear outline of the page and allow users to navigate efficiently. These landmarks are often defined with native semantic HTML tags:


<header> Defines a "banner" region.
<nav> Defines a navigation block.
<main> Defines the primary, unique content of the page.
<footer> Defines a "contentinfo" region.
role="region" Used on a non-landmark element (<div>) to create a custom, meaningful section. Requires aria-label or aria-labelledby.

Let's take the Wikipedia main page (https://en.wikipedia.org/wiki/Main_Page) as example:

Wikipedia page with highlighted landmark sections

The page is divided into well-defined landmarks. The <header> contains the site logo, search bar, and global navigation links. The <nav> element is used for the sidebar menu, including links to languages, portals, and other key sections. The central <main> landmark holds the featured articles, news highlights, and other primary content. Side content, for changing the appearance or other supplementary links, is wrapped in <aside>. At the bottom, the <footer> includes site-wide links, legal information, and additional navigation.

By using landmarks in this way, the page provides screen-reader users with quick navigation and helps search engines understand the structure of the page.

Custom Regions

While using the semantic HTML tags is great, sometimes your app requires custom regions for more complex layouts where existing landmark roles are not appropriate. You can create these regions with ARIA roles to maintain accessibility without breaking semantic structure.

<div aria-label="Related Articles" role="region">
  …content…
</div>

That way, your custom region gets the same accessibility benefits as the native HTML tags.

Why Landmarks Matter

Quick navigation

Screen-reader users can jump between landmarks to reach relevant sections instantly, instead of navigating through the entire DOM. This improves efficiency and overall user experience.

Better semantics

Landmarks provide clear meaning to the page structure, helping both assistive technologies and search engines to understand your content. Proper semantics can also improve SEO by signaling the importance of different sections.

SPAs and dynamic app

React apps often update content without full page reloads. Using proper landmarks ensures that users can stay oriented even as the DOM changes, making dynamic applications more accessible and predictable.

Structural accessibility

Many developers focus on visual accessibility, such as color contrast and font sizes, but structural accessibility is equally important. Landmarks provide a clear page hierarchy and accessible navigation, which is often neglected in modern web apps.

Reusable React Components for Landmarks

When building many pages, it’s worth creating small reusable components to enforce semantics and accessibility consistently while reducing repetitive code.

For example, to make sure that each page has an accessible main content area, you can create a component that uses the native <main> landmark. That way you can also reuse the same style of the main content across pages such as spacing, padding, colors etc.

import React, { type ReactNode } from 'react';

interface MainProps {
  children?: ReactNode;
}

const Main: React.FC<MainProps> = ({ children }) => {
  return <main className="main">{children}</main>;
};

export default Main;

But, keep in mind that there should only be one <main> element (or role="main") per document. This is a fundamental rule that ensures screen reader users can reliably jump to the primary content.

And, as I mentioned previously, sometimes your layout requires sections that are not covered by native landmarks like <main>. In these cases, you can create custom regions using a <div> with role="region" and an accessible label via aria-label or aria-labelledby. This will help assistive technologies identify and navigate these areas effectively.

Here is an example of such component:

import React, { type ReactNode } from 'react';

interface RegionProps {
  children?: ReactNode;
  label: string;
  labeledBy: string;
}

const Region: React.FC<RegionProps> = ({ children, label, labeledBy }) => {
  return (
    <div role="region" aria-label={label} aria-labelledby={labeledBy} className="region">
      {children}
    </div>
  );
};

export default Region;

In most cases, custom sections will have a visible heading, in which case the ID of the heading element should be linked through the labeledBy prop. In other cases, simply passing an accessible heading title throughlabel prop will do fine.

Example usage:

<Region label="My Custom Region">
  <p>My Custom Region content goes here.</p>
</Region>

The image below shows the custom region in action, as identified by the Accessibility Insights tool. You can see how the Region component is recognized as a landmark with a clear, accessible label, making it easy for screen-reader users to understand and navigate the page structure.

Custom region landmark highlighted in Accessibility Insights for React dashboard layout

One important thing to note here is to not overuse role="region". If role="region" is appled to too many small <div>s, it pollutes the list of available landmarks for screen reader users, making the navigation process less efficient (defeating the purpose of landmarks). role="region" should only be used for major, meaningful sections (e.g., a "Related Products" area or a "Filtering Controls" panel) that a user would genuinely want to jump to, rather than for every minor grouping of content.

You can find the source code for this component as well as other accessible ready-to-use components for a Dashboard Layout here.

Best‑Practices Checklist

  • ✅ Prefer semantic HTML tags (<header>, <nav>, <main>, <aside>, <footer>)
  • ✅ Use only one <main> element (or role="main") per document
  • ✅ Use role="region" only for major, meaningful sections
  • ✅ Always label custom regions with aria-label
  • ✅ Use reusable components to maintain accessibility consistently
  • ✅ Combine landmarks with skip links for keyboard users
  • ✅ Test your app with screen readers and keyboard navigation. Semantic landmarks alone are not enough.

Summary

Landmarks and regions help create a clear structure that screen readers can understand instantly, making navigation faster and more predictable. Using semantic elements like header, nav, main, and footer sets a strong foundation, while custom regions fill in the gaps for areas that need their own identity. With reusable React components, it becomes easy to apply this structure across an entire app. The dashboard example shows how each part is recognized in Accessibility Insights, confirming that the layout is well-organized, accessible, and ready to scale.

Jump to Post Summary
Post a Comment (0)
Previous Post Next Post