Skip Navigation
amb

Archived Post: How I Added a Skip Navigation Link to My Next.js Site

🚨 ATTENTION 🚨

You are currently viewing an archived post. The information here may no longer be accurate or maybe Ashlee just decided not to publish the post as publicly anymore.

Many sites on the web have the same content at the top of every page. The content is commonly a logo that links to the home page and then several links to the main pages of the site. If you navigate the same site regularly, you probably find these navigation links repetitive because you learn to know what's already there. Even when you follow a link to a site you've never been to before, you probably expect there to be a set of navigation links at the top. If you're just trying to read the content of the page and don't care about the header, you'll find Skip Navigation links useful.

Skip Navigation Link are pretty straightforward. They enable people to skip the navigation at the beginning of a site and get to the main content of the page. This is really helpful for people who navigate sites without a pointer device, such as a keyboard. Without a Skip Navigation Link, a keyboard user would have to tab through every link, button, etc. that appears before the main page content. While tabbing might not be a difficult task for you personally, it is often more difficult for disabled users, so it's necessary to prevent that difficulty.

Skip Navigation Links fall under Web Content Accessibility Guideline 2.4: Provide ways to help users navigate, find content and determine where they are. The first Success Criterion for this guideline is called Success Criterion 2.4.1: Bypass Blocks, and within that is Technique G1: Adding a link at the top of each page that goes directly to the main content area. The writeup for Technique G1 lists the following as requirements for Skip Navigation Links that go to the main content of a page:

  1. Check that a link is the first focusable control on the Web page.
  2. Check that the description of the link communicates that it links to the main content.
  3. Check that the link is either always visible or visible when it has keyboard focus.
  4. Check that activating the link moves the focus to the main content.
  5. Check that after activating the link, the keyboard focus has moved to the main content.

What does the code look like?

I just used a little CSS and JSX for my Skip Navigation Link, and I opted for making it visible only when it gets keyboard focus. On my site, I use Next.js Per-Page Layouts to help me render repeated content, such as navigation links, on many pages. The layout I use for the navigation header is where I placed a Skip Navigation Link. The code looks something like this:

import styles from './base-layout.module.css';

const BaseLayout = ({ children }) => {
  return (
    <div className={styles.baseLayoutContainer}>
      <a className={styles.skipNavigationLink} href="#main-content">
        Skip Navigation
      </a>
      <SiteHeader />
      <main id="main-content" className={styles.mainElement} tabIndex={-1}>
        {children}
      </main>
      <SiteFooter />
    </div>
  );
};

What's important to note from this code:

  1. The Skip Navigation Link is before the SiteHeader component that I built for rendering navigation links on my site. Remember: the link must be the first focusable control on the page.
  2. The Skip Navigation Link's href property references the id of the main element where I render the content of a page.
  3. The main element that I'm linking to with the Skip Navigation Link has tabIndex set to -1. This makes the element focusable but does not include it in the page's tab order. Further reading from TPGi: Using the tabindex attribute.

After I figured out the markup, I applied CSS to hide the Skip Navigation Link when not focused and also some CSS to remove the focus outline from the main element. The code looks something like this:

.baseLayoutContainer {
  position: relative;
}

.skipNavigationLink {
  left: -10000px;
  position: absolute;
  z-index: 1;

  &:focus {
    left: 0;
  }
}

.mainElement:focus {
  outline: none;
}

What's important to note from this code:

  1. The parent container of the Skip Navigation Link, specified by the baseLayoutContainer class name, has position: relative set. This is important because position: absolute is set on the Skip Navigation Link.
  2. The Skip Navigation Link has position: absolute, left: -10000px, and z-index: 1 set. This set of properties places the link off the left side of the page by 10,000 pixels and ensures it's placed on top of other elements using z-index. You may have to tweak this value if you have used it in other places in your app.
  3. When the Skip Navigation Link is focused, the left position is updated to 24px, moving it to be in view in the page.
  4. When the main element (specified by the mainElement class name) is focused, outline is set to none so that no focus outline shows on the element after navigating to it with the Skip Navigation Link.

Conclusion and Further Reading

And that's all! Skip Navigation Links are a super quick accessibility win with a ton of value since they help so many folks. Celebrate your quick win and keep the momentum going! Consider adding a scroll-to-top link next if you haven't already.

Further reading

Back to Top