Skip-to-Content Accessibility Link
By Amr
WCAG 2.1 Level AA compliant skip link for keyboard users to bypass navigation and jump to main content.
Estimated reading time: 4 minutes
Table of Contents
Skip-to-Content Accessibility Link
The Zer0-Mistakes theme includes a WCAG 2.1 Level AA compliant skip link that allows keyboard users to bypass navigation.
Overview
The skip-to-content link:
- Visually Hidden: Only visible on keyboard focus
- First Focusable: Appears immediately on Tab
- Direct Navigation: Jumps to main content area
- WCAG Compliant: Meets accessibility standards
How It Works
User Flow
- User arrives on page
- Presses
Tabkey - “Skip to main content” link becomes visible
- User presses
Enter - Focus moves to main content
Implementation
<!-- In _includes/core/header.html -->
<a href="#main-content" class="skip-link visually-hidden-focusable">
Skip to main content
</a>
<!-- Main content area -->
<main id="main-content" tabindex="-1">
<!-- Page content -->
</main>
Styling
Default Styles
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: var(--bs-primary);
color: white;
padding: 8px 16px;
z-index: 9999;
transition: top 0.3s ease;
}
.skip-link:focus {
top: 0;
}
Bootstrap Utility
Using Bootstrap’s visually-hidden-focusable:
<a href="#main-content" class="visually-hidden-focusable">
Skip to main content
</a>
This class:
- Hides element visually
- Keeps it accessible to screen readers
- Shows on keyboard focus
Customization
Link Text
<!-- Custom text -->
<a href="#main-content" class="skip-link visually-hidden-focusable">
Jump to content
</a>
Styling
/* Custom styling */
.skip-link:focus {
background: var(--bs-dark);
color: var(--bs-light);
border-radius: var(--bs-border-radius);
box-shadow: var(--bs-box-shadow);
}
Position
/* Center the link */
.skip-link:focus {
left: 50%;
transform: translateX(-50%);
}
/* Right-aligned */
.skip-link:focus {
left: auto;
right: 1rem;
}
Multiple Skip Links
For complex pages with multiple sections:
<div class="skip-links">
<a href="#main-content" class="skip-link visually-hidden-focusable">
Skip to main content
</a>
<a href="#navigation" class="skip-link visually-hidden-focusable">
Skip to navigation
</a>
<a href="#footer" class="skip-link visually-hidden-focusable">
Skip to footer
</a>
</div>
WCAG Compliance
Requirements Met
| Criterion | Status |
|---|---|
| 2.4.1 Bypass Blocks (A) | ✅ |
| 2.1.1 Keyboard (A) | ✅ |
| 2.4.3 Focus Order (A) | ✅ |
| 2.4.7 Focus Visible (AA) | ✅ |
Best Practices
- First Link: Skip link should be first focusable element
- Clear Text: Use descriptive link text
- Visible on Focus: Must become visible when focused
- Valid Target: Target element must exist and be focusable
Testing
Manual Testing
- Load page
- Press
Tabimmediately - Verify skip link appears
- Press
Enter - Confirm focus moves to main content
Automated Testing
// Accessibility test
describe('Skip Link', () => {
it('should be first focusable element', () => {
cy.get('body').tab();
cy.focused().should('have.class', 'skip-link');
});
it('should skip to main content', () => {
cy.get('.skip-link').focus().click();
cy.focused().should('have.id', 'main-content');
});
});
Screen Reader Testing
Test with:
- NVDA (Windows)
- VoiceOver (macOS)
- JAWS (Windows)
The link should announce:
“Skip to main content, link”
Troubleshooting
Link Not Appearing
- Check element exists in DOM
- Verify CSS isn’t hiding it
- Ensure JavaScript isn’t interfering
Link Not Working
- Verify target ID exists (
#main-content) - Check target has
tabindex="-1" - Test without JavaScript
Focus Not Moving
- Add
tabindex="-1"to target - Check for focus traps
- Verify no
e.preventDefault()on links