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


