Back to Blog
How to Add a Skip-to-Content Link to a Shopify Theme (WCAG 2.4.1) — featured image

How to Add a Skip-to-Content Link to a Shopify Theme (WCAG 2.4.1)

Author avatarVijaygopal Balasa
6 min read

A skip-to-content link is a common technique for WCAG 2.1 SC 2.4.1 (Bypass Blocks, Level A), which requires a mechanism to bypass repeated blocks rather than prescribing one universal implementation. Theme versions and customizations differ. This guide provides an adaptable pattern for a store that lacks a working bypass mechanism.

Skip-to-content links serve users who navigate by keyboard or assistive technology. Without one, a screen-reader user reaching your storefront has to listen through the full header (logo, search, cart, account, navigation, mega-menu, announcement bar) on every page before reaching the actual page content. With one, pressing Tab once focuses the skip link; pressing Enter jumps focus and screen-reader cursor directly to the main content.

The link is normally revealed when keyboard focus reaches it. The pattern is widely supported, but test it with the store's supported browsers and assistive technologies and do not assume mouse users can never encounter it.

The implementation

Open sections/header.liquid (Online Store 2.0 themes) or layout/theme.liquid (Online Store 1.0 themes) in the Shopify admin → Online Store → Themes → Edit code. Find the opening <header> tag and add the skip link immediately before it:

<a class="skip-to-content-link" href="#MainContent">
  Skip to content
</a>
<header>
  ...
</header>

The href="#MainContent" should match the ID on the main content wrapper. In Dawn that wrapper is <main id="MainContent">. In other themes it might be <main id="main-content"> or similar — check your theme.liquid for the existing main element ID.

Step 2 — Add the visually-hidden + focus-visible CSS

Add this block to assets/base.css (or your theme's primary stylesheet):

.skip-to-content-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  padding: 0.75rem 1rem;
  background: #0a0a0a;
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  /* Hide visually but keep in the accessibility tree */
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  overflow: hidden;
  white-space: nowrap;
}

.skip-to-content-link:focus {
  /* Reveal on keyboard focus */
  clip: auto;
  clip-path: none;
  height: auto;
  width: auto;
  overflow: visible;
  white-space: normal;
  outline: 3px solid #f97316;
  outline-offset: 2px;
}

The crucial detail is clip: rect(0 0 0 0) plus position: absolute — this hides the element visually but keeps it in the accessibility tree and focusable. Using display: none would remove it from the tab order entirely, defeating the purpose.

Step 3 — Verify the target exists and is focusable

The skip link only works if the target element can receive focus. Find your <main> element in layout/theme.liquid:

<main id="MainContent" tabindex="-1">
  {{ content_for_layout }}
</main>

tabindex="-1" lets the element receive programmatic focus from the skip link without inserting it into the natural Tab order. Without tabindex="-1", Safari and some other browsers will scroll to the target but not move keyboard focus there — the screen-reader announcement misses.

Per-theme variations

ThemeAlready ships skip link?Notes
Current or customized themeVerifyInspect the published version, focus behavior, link target, and styles.
Legacy theme copyVerifyHistorical versions and merchant edits differ; do not add a duplicate before testing.
App-provided shell or headerCoordinateIdentify code ownership and ask the vendor to remediate app-owned focus order or markup.

Common mistakes to avoid

display: none instead of clipping

/* WRONG — removes from accessibility tree */
.skip-to-content-link {
  display: none;
}
.skip-to-content-link:focus {
  display: block;
}

display: none makes the element unreachable by Tab. Use the clip: rect(0 0 0 0) pattern instead.

Some themes ship a skip link in sections/header.liquid and another in layout/theme.liquid from a partial migration. Two skip links pointing at the same target confuse screen-reader users. Keep one.

A theme that hides the skip link via @media (max-width: 768px) { display: none } fails 2.4.1 on mobile. Mobile keyboard users (Bluetooth keyboards, switch-control devices) rely on it just as much as desktop.

The skip link must be the first focusable element in document order. If a "Cart" icon button precedes it, keyboard users hit Cart first and never reach the skip link. Move it above every other interactive element in header.liquid.

How to verify it works

  1. Open your storefront in any browser.
  2. Click in the URL bar to clear focus.
  3. Press Tab once. The skip link should appear in the top-left corner with a high-contrast outline.
  4. Press Enter. The page should scroll to (and focus on) the main content area.
  5. Press Tab again. The next focused element should be inside the main content, not back in the header.

If steps 3, 4, or 5 fail, check the corresponding section above.

Why this is a deterministic fix

A skip link has structural parts that automation can inspect, but correct focus movement and usefulness still require keyboard and assistive-technology testing. AccessComply can propose an eligible, safely source-mapped first-party change for merchant review through a supported theme path and run a post-change check. Re-test after material theme, header, or app changes.

Further reading

Free scan available

Find the storefront issues holding back growth

Scan SEO, speed, and accessibility by page. Review supported fixes before they run, keep saved originals, and verify the live result afterward.

Vijaygopal Balasa, Founder, AccessComply
Written by

Vijaygopal Balasa

Founder, AccessComply

Founder of AccessComply. Builds tools that find and fix supported Shopify accessibility issues in theme code—not through overlays. Focused on practical WCAG 2.2 AA improvements for merchants.

Keep improving after this fix.

Get concise, practical updates on Shopify SEO, speed, accessibility, and safer storefront changes. No daily noise; unsubscribe anytime.

More on EAA

See all →