# The skip-link target should exist and be focusable

> Canonical HTML version: https://rocketvalidator.com/accessibility-validation/axe/4.11/skip-link
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

Screen readers and keyboard-only navigation process page content sequentially, following the DOM order. This means that everything before the main content — site logos, navigation bars, search forms, utility links — must be traversed before a user reaches what they actually came for. On complex sites, this repetitive content can be extremely lengthy.

A properly functioning skip link gives these users a shortcut. When the skip link's target is missing or not focusable, activating the link does nothing. The user remains at the top of the page with no indication of what went wrong, which is both confusing and frustrating.

This issue primarily affects:

- **Blind and deafblind users** who rely on screen readers to navigate sequentially.
- **Keyboard-only users** (including those with mobility impairments) who tab through every interactive element.
- **Sighted keyboard users** who benefit from the visual skip link appearing on focus.

This rule is a **Deque best practice** and aligns with **WCAG technique G1** ("Adding a link at the top of each page that goes directly to the main content area"), which supports **WCAG 2.4.1 Bypass Blocks** (Level A). Success Criterion 2.4.1 requires that a mechanism exists to bypass blocks of content repeated across multiple pages.

## How to Fix It

1. **Add a skip link as the very first focusable element** inside the `<body>` tag, before any navigation or repeated content.
2. **Set the `href` to a fragment identifier** (e.g., `#main-content`) that matches the `id` of the target element.
3. **Ensure the target element exists** in the DOM with the corresponding `id`.
4. **Make the target focusable** if it is not natively focusable. Non-interactive elements like `<div>` or `<main>` need `tabindex="-1"` so the browser can move focus to them when the skip link is activated.
5. **Do not hide the skip link with `display: none` or `visibility: hidden`**, as these make the link inaccessible to all users, including screen reader users.

### Handling the Skip Link's Visibility

You can make the skip link visually hidden until it receives keyboard focus. This approach keeps the layout clean for mouse users while remaining fully accessible to keyboard users:

- Use CSS to position the link off-screen by default.
- On `:focus`, bring it back on-screen so sighted keyboard users can see it.

Alternatively, you can make the skip link permanently visible — this is the simplest and most inclusive approach.

**Important:** Never use `display: none` or `visibility: hidden` on the skip link. These properties remove the element from the accessibility tree and the tab order, making it useless for everyone.

## Examples

### Incorrect: Skip Link Target Does Not Exist

The skip link points to `#main-content`, but no element with that `id` exists on the page.

```html
<body>
  <a href="#main-content">Skip to main content</a>
  <nav>
    <a href="/">Home</a>
    <a href="/about">About</a>
    <a href="/contact">Contact</a>
  </nav>
  <main>
    <h1>Welcome</h1>
    <p>Page content goes here.</p>
  </main>
</body>
```

### Incorrect: Target Exists but Is Not Focusable in Some Browsers

Some older or WebKit-based browsers may not move focus to a non-interactive element even with a matching `id`, unless `tabindex="-1"` is added.

```html
<body>
  <a href="#main-content">Skip to main content</a>
  <nav>
    <a href="/">Home</a>
    <a href="/about">About</a>
  </nav>
  <div id="main-content">
    <h1>Welcome</h1>
    <p>Page content goes here.</p>
  </div>
</body>
```

### Correct: Skip Link with a Focusable Target

The target element has both a matching `id` and `tabindex="-1"` to ensure it receives focus reliably across all browsers.

```html
<body>
  <a href="#main-content" class="skip-link">Skip to main content</a>
  <nav>
    <a href="/">Home</a>
    <a href="/about">About</a>
    <a href="/contact">Contact</a>
  </nav>
  <main id="main-content" tabindex="-1">
    <h1>Welcome</h1>
    <p>Page content goes here.</p>
  </main>
</body>
```

### Correct: Skip Link That Is Visually Hidden Until Focused

This CSS pattern hides the skip link off-screen by default and reveals it when the user tabs to it.

```html
<body>
  <a href="#main-content" class="skip-link">Skip to main content</a>
  <nav>
    <a href="/">Home</a>
    <a href="/about">About</a>
  </nav>
  <main id="main-content" tabindex="-1">
    <h1>Welcome</h1>
    <p>Page content goes here.</p>
  </main>
</body>
```

```css
.skip-link {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.skip-link:focus {
  position: static;
  width: auto;
  height: auto;
  overflow: visible;
  padding: 8px 16px;
  background: #ffc;
  border: 2px solid #990000;
  z-index: 1000;
}
```

### What the Rule Checks

This axe-core rule (`skip-link`) verifies that every skip link on the page — typically the first link in the document — has a target that both exists in the DOM and is focusable. If the `href` points to a fragment identifier like `#main-content`, the rule confirms that an element with `id="main-content"` is present and can receive focus.
