Skip to content

Navigation

Skip Link

A hidden link that lets keyboard users jump past repeated content.

When to use it: Use it as the first focusable element so keyboard users can bypass navigation (WCAG 2.4.1).

On this page

Example

Loading example…
Skip Link.tsxtsx
import { SkipLink } from "@comp0/react";

export function Example() {
  return (
    <div className="flex w-64 flex-col gap-3 text-base text-zinc-800 sm:text-sm dark:text-zinc-100">
      <SkipLink
        href="#skip-link-main"
        className="self-start rounded bg-teal-700 px-3 py-2 text-white outline-offset-2 focus-visible:outline-2 focus-visible:outline-teal-600 dark:bg-teal-400 dark:text-zinc-950 dark:focus-visible:outline-teal-300"
      >
        Skip to main content
      </SkipLink>
      <p className="text-zinc-600 dark:text-zinc-400">
        Press Tab from the start of this example to reveal the link.
      </p>
      <nav aria-label="Example" className="flex gap-3">
        <a className="underline underline-offset-4" href="#skip-link-home">
          Home
        </a>
        <a className="underline underline-offset-4" href="#skip-link-docs">
          Docs
        </a>
        <a className="underline underline-offset-4" href="#skip-link-blog">
          Blog
        </a>
      </nav>
      <main
        id="skip-link-main"
        tabIndex={-1}
        className="rounded border border-zinc-950/10 p-3 dark:border-white/10"
      >
        Main content starts here.
      </main>
    </div>
  );
}

Landmark page shell

Pair the first skip link with native header, nav, main, and footer landmarks.

Loading example…
skip-link.page-shell.tsxtsx
import { SkipLink } from "@comp0/react";

export function Example() {
  return (
    <div className="grid min-h-80 grid-cols-[9rem_1fr] grid-rows-[auto_1fr_auto] overflow-hidden rounded-xl border border-zinc-950/15 text-base sm:text-sm dark:border-white/15">
      <SkipLink
        href="#shell-main"
        className="absolute z-10 m-2 rounded bg-teal-700 px-3 py-2 text-white outline-offset-2 focus-visible:outline-2 dark:bg-teal-400 dark:text-zinc-950"
      >
        Skip to main content
      </SkipLink>
      <header className="col-span-2 border-b border-zinc-950/10 p-4 font-semibold dark:border-white/10">
        Project Atlas
      </header>
      <nav aria-label="Project" className="border-r border-zinc-950/10 p-4 dark:border-white/10">
        <ul className="space-y-2">
          <li>
            <a href="#overview" className="underline underline-offset-2">
              Overview
            </a>
          </li>
          <li>
            <a href="#activity" className="underline underline-offset-2">
              Activity
            </a>
          </li>
        </ul>
      </nav>
      <main
        id="shell-main"
        tabIndex={-1}
        className="scroll-mt-4 p-4 outline-teal-600 focus-visible:outline-2 dark:outline-teal-400"
      >
        <h1 className="text-lg font-semibold">Overview</h1>
        <p className="mt-2 text-zinc-600 dark:text-zinc-400">
          Native landmarks give assistive technology a map of the page.
        </p>
      </main>
      <footer className="col-span-2 border-t border-zinc-950/10 p-4 text-zinc-600 dark:border-white/10 dark:text-zinc-400">
        Project support
      </footer>
    </div>
  );
}

Anatomy

Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.

A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.

  1. SkipLink

    Native anchor that stays visually hidden until it receives focus. Owns a DOM element.

Step by step

  1. 1

    Add the main part

    Put SkipLink first inside body, before the repeated navigation.

  2. 2

    Add the supporting parts

    Point href at the main content, such as "#main".

  3. 3

    Make the behavior clear

    Give the target element the matching id and tabIndex={-1} so focus lands there.

    Exampletsx
    <SkipLink href="#main">Skip to main content</SkipLink>;

Keyboard

Reveals the link when it receives focus.
Jumps to the target and hides the link again.

Forms and accessibility

No form behavior.

Accessibility checklist

  • Make it the first focusable element on the page.
  • Style the revealed state clearly; it appears exactly when a keyboard user needs it.
  • Point href at a real element with a matching id, and give that target tabIndex={-1}.
  • Use native header, nav, main, aside, and footer landmarks so assistive technology can navigate the page structure directly.

API reference

Importtsx
import { SkipLink } from "@comp0/react";

SkipLink

DOM element

Native anchor that stays visually hidden until it receives focus.

PropTypeDescription
hrefstringIn-page target the link jumps to, such as "#main".
classNamestringStyles the revealed link; merged with the hiding styles while hidden.
styleCSSPropertiesStyles the revealed link; merged with the hiding styles while hidden.

Style hooks

Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.

SkipLink

Style hookMeaning
[data-focused]The link is focused and visible.
:focus-visibleNative keyboard-focus styling hook.

Keep exploring