Loading...

Skip to main content

Add a ‘skip to content’ link to your website

When a user interacts with your website using a keyboard, they might have to tab through your navigation links before getting to the main content. We want to give keyboard-only users the option to skip the navigation, without affecting the experience for other users. To do this, we can hide the skip navigation link until it’s focused.

Markup

First, we need to properly set up our HTML. Let’s add a unique id to your main content container, excluding the navigation.

index.html

<nav>...</nav> <main id="mainContent">...</main>


Our skip navigation link should have a clear CTA, and we use the id we set previously as the destination.

index.html

<a id="skiptocontent" href="#mainContent">Skip to main content</a>

Styles

Now we can style the link and animate in on focus. Here it’s fading in from the top of the screen but feel free to tinker or remove the animation.

styles.css

#skiptocontent { position: absolute; top: 0; left: 0; z-index: 200; opacity: 0; transform: translateY(-100%); transition: all 250ms ease-out; &:focus { opacity: 1; transform: translateY(0); } }

WCAG Success Criteria

  • A link is the first focusable control on the Web page.
  • The description of the link communicates that it links to the main content.
  • The link is either always visible or visible when it has keyboard focus.
  • Activating the link moves the focus to the main content.
  • After activating the link, the keyboard focus has moved to the main content.

View full criteria(Opens in a new tab)

Notes

If you decide to animate the skip navigation link, make sure to respect your users’ browser preferences and disable animations when requested.

styles.css

#skiptocontent { position: absolute; top: 0; left: 0; z-index: 200; opacity: 0; transform: translateY(-100%); @media (prefers-reduced-motion: no-preference) { transition: all 250ms ease-out; } &:focus { opacity: 1; transform: translateY(0); } }


You can also disable every animation on your website like so:

styles.css

@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }

Demo

import { Toaster } from "react-hot-toast";
import { Navigation } from "./components/Navigation";
import { useDemoProps } from "./hooks/useDemoProps";

import "./styles/styles.scss";

export default function App() {
  const { demoLinkProps, demoTriggerProps } = useDemoProps();

  return (
    <>
      <a
        id="skiptocontent"
        href="#mainContent"
        // The following props are for demo purposes only
        // DO NOT copy the following line
        {...demoLinkProps}
      >
        Skip to main content
      </a>
      <Navigation />
      <main id="mainContent">
        <h1>Main content</h1>
        <p>
          Use your keyboard's <kbd>Tab</kbd> key to show or hide the skip
          navigation button. You might be running into some issues with the tab
          order since this demo is in an iframe.
          <button {...demoTriggerProps}>
            Click here to manually trigger focus on the button.
          </button>
        </p>
        <p>
          If you press your keyboard's enter key while the button is focused, it
          will move focus to the main content and ignore the nav links above.
        </p>
        <Toaster />
      </main>
    </>
  );
}