
Element Code: PE-034
What "content outside landmarks" actually means
Landmarks are the small set of ARIA roles, and their matching HTML5 elements, that describe the big regions of a page: banner (usually your <header>), navigation (<nav>), main (<main>), complementary (<aside>), contentinfo (<footer>), and a few less common ones like search and form. Screen readers expose these as a jump list, similar to the way sighted users skim a page by its visual layout. Press the landmarks shortcut in NVDA or VoiceOver and you get a menu: header, nav, main, footer. That is the whole point of landmarks, letting a non-visual user teleport straight to the section they want instead of tabbing through everything in document order.
Content outside landmarks is any markup that sits between those regions, or floats inside the body without being wrapped in one. Picture a promotional banner injected by a tag manager sitting directly under <body>, a cookie notice appended outside <main>, or a widget from a page builder that drops its own wrapper div right before the footer, outside both <main> and <footer>. Visually it looks fine. Structurally it is a blind spot. A screen reader user who jumps to "main" and then to "footer" via the landmarks menu will never encounter that content at all, because it does not belong to any landmark, it just sits between them.
Why it matters for SEO and accessibility together
This is not a checkbox for a legal audit, it changes what content actually gets discovered and used. Content orphaned outside landmarks does not disappear from the DOM, so it still gets indexed by Google, but it becomes functionally invisible to landmark-based navigation, which is how a large share of screen reader users actually browse. WCAG 1.3.1 (Info and Relationships) and the ARIA11 technique both call for wrapping page content in landmarks specifically so structure is communicated programmatically, not just visually.
There is a practical SEO angle too, in my experience these orphaned blocks are usually a symptom of something a bit worse: markup injected by a third party script, an A/B test tool, or a badly scoped page builder module, sitting outside the semantic structure of the template. That is often the same code responsible for layout shift, duplicate IDs, or content that renders after the initial paint. Fixing the landmark placement is frequently the moment you notice the underlying script is also causing other problems, so treat this audit finding as a flag to go look at what generated that div, not just a wrapper to slap on.
How to detect it
- Browser DevTools, Elements panel: inspect the DOM tree and look for any direct child of
<body>that is not<header>,<nav>,<main>,<aside>, or<footer>(or an element carrying the matchingroleattribute). - axe DevTools or axe-core: run a scan, the "all page content should be contained by landmarks" rule flags exactly this.
- Lighthouse accessibility audit: surfaces the same landmark-coverage check in Chrome DevTools under the Accessibility category.
- Screaming Frog: use custom extraction with an XPath rule to pull anything outside
main|header|nav|aside|footerat scale across a full crawl, useful when you suspect a template-level pattern rather than a one-off page. - Manual screen reader pass: open the landmarks list in NVDA (Insert+F7) or VoiceOver's rotor, then compare it against everything visible on the rendered page. Anything you can see but cannot reach through the landmarks list is your orphan.
How to fix it, step by step
- Identify every orphaned block by DOM position, not just visually. Note what generated it: a template partial, a tag manager snippet, a plugin, a widget.
- Pick the correct landmark for its purpose. A promo banner tied to navigation can live inside
<header>. A cookie or consent notice often belongs wrapped in a<div role="region" aria-label="Cookie notice">if it truly is not part of any of the five core landmarks. Don't force everything into<main>just because it is the biggest bucket, that dilutes what "main content" means for the one landmark that matters most for skip-to-content. - Use native HTML5 sectioning elements first (
<header>,<nav>,<main>,<aside>,<footer>) over bare ARIA roles. They get you the landmark for free with better default browser and AT support. - If a third party script injects the offending markup, you often cannot edit its output directly, so wrap its container in your template with an appropriate role instead of fighting the vendor's code.
- Never nest a landmark of the same type inside another without a label. Two
<nav>elements need distinctaria-labelvalues ("Primary" vs "Footer") so the landmarks list does not just show "navigation, navigation" with no way to tell them apart. - Re-run the axe or Lighthouse scan and confirm zero elements outside landmark coverage, then do the manual screen reader pass again to confirm the fix reads correctly, not just structurally.
| Landmark role | HTML5 element | Typical content |
|---|---|---|
| banner | <header> | Logo, site title, top-level promo |
| navigation | <nav> | Primary menu, breadcrumbs, footer links |
| main | <main> | The unique content of the page, one per page |
| complementary | <aside> | Related links, sidebar widgets |
| contentinfo | <footer> | Copyright, legal, contact info |
| search | role="search" | Site search form |
- Wrap every direct child of body in a landmark or role
- Use one
<main>per page, no exceptions - Label duplicate landmark types with
aria-label - Audit third party script output for orphaned wrappers
- Re-check with a real screen reader, not just an automated scanner
- Leave tag manager banners floating outside header or main
- Stuff unrelated content into main just to get it "in a landmark"
- Use multiple unlabeled nav elements
- Assume Lighthouse's automated pass caught everything, it misses ambiguous cases
- Skip the fix because it "looks fine visually"
What good looks like
Every direct child of <body> is either a landmark element or explicitly excluded on purpose (a skip link is the one common exception, it typically sits first in the DOM before the header). A screen reader user pulling up the landmarks list sees a small, labeled set: banner, navigation, main, complementary, contentinfo, maybe search, and nothing else lurking between them. Third party injected content lives inside a labeled region, not bolted onto the body tag raw. When you run axe or Lighthouse, the landmark coverage check comes back clean, and when you actually tab or use rotor navigation, nothing on the visible page is unreachable.
Does content outside landmarks hurt my Google rankings directly?
Can I just wrap everything in one big div with role="main" and call it done?
What about skip links, do they need to be inside a landmark?
My page builder keeps injecting a stray div, how do I fix it without editing core plugin code?
Is this check the same as "missing main landmark"?
Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.
About SEO ProCheck
Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.
Work With Me
Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.







