Structure and landmarks Rule

Give people a way to skip past repeated navigation bypass

Most pages start with the same header and menu. Someone using a keyboard has to tab through every one of those links on every page before reaching the content. A skip link at the top of the page, a main landmark and proper headings each give a way to jump past the repeated blocks. The scanner wants at least one; a good page has all three.

WCAG 2.2 A 2.4.1 Bypass Blocks

Websight reports this as Page must have means to bypass repeated blocks

Who it affects

Someone with a motor impairment using a keyboard on a district council website presses Tab 34 times on every page to get past the menu, and the same again after every search.

Someone who is blind using a screen reader has no landmarks or headings to jump to, so has to listen to the menu read out again on each page.

Someone using a switch, one press at a time gives up on a page before reaching the form they came for.

Broken versus fixed

Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.

Broken

Click inside the frame and press Tab. Ten presses to get past the menu, and there is no heading or main landmark to jump to instead.

Fixed

Click inside the frame and press Tab once. A Skip to content link appears; Enter moves focus straight to the main content, which also has a heading and a main landmark.

Show the markup behind both examples
Broken
<style>body{font-family:system-ui;margin:0;padding:12px}nav a{display:inline-block;margin:0 10px 6px 0;color:#1b5e9e}nav a:focus{outline:3px solid #e07a1f}.content{margin-top:10px;padding-top:10px;border-top:1px solid #ddd}</style>
<nav>
  <a href="#home">Home</a><a href="#bins">Bins</a><a href="#council-tax">Council tax</a><a href="#planning">Planning</a><a href="#parking">Parking</a>
  <a href="#housing">Housing</a><a href="#schools">Schools</a><a href="#libraries">Libraries</a><a href="#leisure">Leisure</a><a href="#contact">Contact</a>
</nav>
<div class="content">
  <p><b>Report a missed bin collection</b></p>
  <p>Tell us which bin was missed and we will collect within two working days.</p>
</div>
Fixed
<style>body{font-family:system-ui;margin:0;padding:12px}nav a{display:inline-block;margin:0 10px 6px 0;color:#1b5e9e}nav a:focus{outline:3px solid #e07a1f}main{margin-top:10px;padding-top:10px;border-top:1px solid #ddd}main:focus{outline:3px solid #e07a1f}.skip{position:absolute;left:-999px;top:8px;background:#fff;padding:8px 12px;border:2px solid #1b5e9e;color:#1b5e9e;font-weight:600}.skip:focus{left:12px;outline:3px solid #e07a1f}</style>
<a href="#main" class="skip">Skip to content</a>
<nav>
  <a href="#home">Home</a><a href="#bins">Bins</a><a href="#council-tax">Council tax</a><a href="#planning">Planning</a><a href="#parking">Parking</a>
  <a href="#housing">Housing</a><a href="#schools">Schools</a><a href="#libraries">Libraries</a><a href="#leisure">Leisure</a><a href="#contact">Contact</a>
</nav>
<main id="main" tabindex="-1">
  <h1 style="font-size:16px;margin:0 0 6px">Report a missed bin collection</h1>
  <p style="margin:0">Tell us which bin was missed and we will collect within two working days.</p>
</main>

Test it by hand in two minutes

  1. Load the page, click in the address bar, then press Tab once. A Skip to content link should appear. Press Enter, then Tab again: focus should now be inside the content, not back in the menu.
  2. With a screen reader running, open the landmark list (the VoiceOver rotor, or Insert+F7 in NVDA and choose Landmarks). There should be a main landmark.
  3. Press H in NVDA, or use the VoiceOver rotor's Headings list. The content should start with a heading.
  4. Check the skip link's target id exists on the page and, if the target is a div, that it has tabindex="-1" so focus really moves.

The fix

Before
<body>
  <header><nav>...ten or more links...</nav></header>
  <div class="content">...</div>
</body>
After
<body>
  <a href="#main" class="skip">Skip to content</a>
  <header><nav>...ten or more links...</nav></header>
  <main id="main" tabindex="-1">...</main>
</body>

Put the skip link first in the body. Hide it off screen until it gets focus, never with display:none. Set it once in the page template.

CSS that hides the link until it is focused

Before
.skip { display: none; }
After
.skip { position: absolute; left: -999px; }
.skip:focus { left: 8px; top: 8px; padding: 8px 12px; background: #fff; outline: 3px solid #1b5e9e; }

display:none takes the link out of the tab order, so nobody can reach it. Moving it off screen keeps it focusable.

Landmarks as well as a skip link

Before
<div class="nav">...</div>
<div class="body">...</div>
<div class="foot">...</div>
After
<nav>...</nav>
<main>...</main>
<footer>...</footer>

Screen reader users jump between landmarks with one key. The elements cost nothing and need no CSS changes.

Common mistakes

  • Hiding the skip link with display:none or visibility:hidden, so it never receives focus.
  • Pointing the skip link at an id that does not exist, or at a div with no tabindex, so focus stays where it was.
  • Placing the skip link after the logo and menu, where it skips nothing.
  • Adding a main landmark but wrapping the header and menu inside it.

WCAG criteria this rule maps to

axe-core tags this rule as WCAG 2.2 level A. It is one of the checks for:

The scanner passes the page if it finds a skip link to an in-page target, a main landmark or a heading. It does not press Tab, so it cannot tell whether the skip link shows up on focus or whether its target really takes focus. Automated tools find only part of the accessibility problems on a page; a pass on this rule is not a pass on the criterion.

Scan your own page for this and 63 other checks

Open any page in Chrome, click Websight, and get a score out of 100 with every issue explained and a draft fix snippet per element.

Add Websight to Chrome

Free scans, no account, nothing leaves your computer. Automated tools find only part of the problems; the extension says so on every report.