Skip to Content
One class. First element in the body, before site nav. The href matches the id on <main>.
Main content. Tab to the skip link to reveal it.
<a href="#main" class="af-skip">Skip to content</a>
<nav class="af-navbar" aria-label="Site">
<a href="#" class="af-navbar-brand">Brand</a>
<ul class="af-navbar-nav">
<li>
<a href="#">Home</a>
</li>
<li>
<a href="#">Docs</a>
</li>
</ul>
</nav>
<main id="main" tabindex="-1">…</main>The skip link stays clipped until it receives keyboard focus. Tab into the example to see it at the start of the viewport.
Target
Section titled “Target”tabindex="-1" on <main> so activating the link moves keyboard focus, not only scroll. Safari will not move focus to an in-page target that is not focusable.
Do not put af-skip inside <nav>. It has to be the first focusable control in the app root.
SPA hosts
Section titled “SPA hosts”Angular, Vue, and other routed apps: put the skip link in the root component, as a sibling of the sticky bar — not inside a transformed layout that creates a stacking context. One #main per routed view. Never nest <main>. tabindex="-1" on <main> still applies.
More than one
Section titled “More than one”Each skip is its own link. Same class, different href.
<a href="#main" class="af-skip">Skip to content</a>
<a href="#sidenav" class="af-skip">Skip to navigation</a>