Adding a Skip Navigation Link in React

June 25, 2023

I wanted to add skip navigation to improve the accessibility of my site.

This is one implementation that can be used with react/next.

this sites navigation with skip link button hidden

Skip navigation links are hidden elements that can be focused with the keyboard that allows the user to skip over a site's navigation.

This assists users by removing a repetitive part of browsing with a keyboard or other assistive devices, allowing the content to be accessed much easier.

this sites navigation with skip link button shown

The Link

The link is placed within the navbar of the site next to the other navigation links and is hidden until it is focused. It is important to place this before the rest of your navigation. The link points to an id that is set on the main element.

If you are using a component library like Mantine with polymorphic components, you can set a button to use an a tag.

<nav>
  <Button className='skip-link' component='a' href='#main'>
    Skip Navigation Links
  </Button>
  // Other links
</nav>

Or you can style an a tag.

<nav>
  <a className='skip-link' href='#main'>
    Skip Navigation Links
  </a>
  // Other links
</nav>

CSS

A CSS class is applied to the link that positions it off the screen to hide it. In this case it is positioned absolute with a translateY of -150%.

When the button is focused, translateY is set to 0 to position the button on the screen. You can use a transition to make this movement smoother and to bring attention to the button.

.skip-link {
  position: absolute;
  transform: translateY(-150%);
  transition: 200ms ease-in;
}

.skip-link:focus {
  transform: translateY(0);
}

main and id

Finally, make sure that main has the id that your link is point to.

This is perfect for a layout component.

<main id='main'>
 {...}
</main>

You can also add smooth scrolling to make the jump to main nice.

html {
  scroll-behavior: smooth;
}

Without changing the url

If you don't want to append #main to the url you can use a click handler instead of an href.

const onClick = (event: React.SyntheticEvent) => {
  event.preventDefault();

  const container: HTMLElement | null = document.querySelector('#main');

  if (container) {
    container.tabIndex = -1;
    container.focus();
    setTimeout(() => container.removeAttribute('tabindex'), 1000);
  }
};

The tabIndex needs to be set to -1 to focus main

<Button className={'skip-link'} onClick={onClick}>
   Skip Navigation Links
</Button>

This does not behave exactly the same, as it will focus the entire main block instead of navigating to the top of it.

It will still start the tab order from the top.