Skip links are one of the most important accessibility features and one of the most overlooked.
They let keyboard users bypass repetitive navigation and jump directly to content. WCAG 2.4.1 (Level A) requires them. Yet most WordPress themes don't include them.
Here's how to add skip links to any theme, with code you can use today.
What Are Skip Links?
A skip link is a hidden anchor link that becomes visible when a keyboard user presses Tab. It typically says "Skip to content" and jumps to the main content area.
For someone using a screen reader or keyboard-only navigation, this means not having to tab through 20 menu items on every single page.
The Basic Implementation
Add this to your theme's functions.php or a custom plugin:
/**
* Add skip link to the beginning of the page
*/
function add_skip_link() {
// Don't show in admin
if ( is_admin() ) {
return;
}
echo '<a class="skip-link screen-reader-text" href="#main-content">Skip to content</a>';
}
add_action( 'wp_body_open', 'add_skip_link', 1 );
The CSS (This Is Where Most Fail)
The skip link must be:
- Invisible by default (but NOT
display: nonescreen readers skip those) - Visible on focus
- High contrast
- Properly positioned
.skip-link {
/* Visually hidden but accessible */
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
word-wrap: normal !important;
}
.skip-link:focus {
/* Visible on focus */
background-color: #000;
color: #fff;
clip: auto !important;
clip-path: none;
display: inline-block;
font-size: 16px;
font-weight: 600;
height: auto;
width: auto;
margin: 0;
overflow: visible;
padding: 15px;
position: fixed;
top: 0;
left: 0;
z-index: 999999;
text-decoration: none;
outline: 2px solid #fff;
outline-offset: 2px;
}
Enqueue it properly:
function enqueue_skip_link_styles() {
wp_enqueue_style(
'skip-link-style',
get_template_directory_uri() . '/css/skip-link.css',
array(),
'1.0.0'
);
}
add_action( 'wp_enqueue_scripts', 'enqueue_skip_link_styles' );
The Target Element Problem
Your skip link points to #main-content. But does that ID exist in your theme?
Check common IDs by theme:
-
Twenty Twenty-Four:
main -
Astra:
contentorprimary -
GeneratePress:
content -
Kadence:
main -
Custom themes: Check your
single.phporindex.php
If your theme doesn't have an ID on the main content wrapper, add one:
// In your theme's template files, find the main content div and add an ID
<main id="main-content" class="site-main">
Or use JavaScript as a fallback:
document.addEventListener('DOMContentLoaded', function() {
// Find common main content elements
const selectors = ['main', '[role="main"]', '#content', '#primary', '.site-main'];
for (const selector of selectors) {
const element = document.querySelector(selector);
if (element && !element.id) {
element.id = 'main-content';
break;
}
}
});
Handling Themes Without wp_body_open
Older themes might not call wp_body_open(). Use a fallback:
function add_skip_link_with_fallback() {
if ( is_admin() ) {
return;
}
// Check if wp_body_open was already called
if ( did_action( 'wp_body_open' ) ) {
return; // Already rendered via wp_body_open
}
// Inject via JavaScript
$html = '<a class="skip-link screen-reader-text" href="#main-content">Skip to content</a>';
?>
<script>
(function() {
var skipLink = <?php echo wp_json_encode( $html ); ?>;
var div = document.createElement('div');
div.innerHTML = skipLink;
document.body.insertBefore(div.firstChild, document.body.firstChild);
})();
</script>
<?php
}
add_action( 'wp_footer', 'add_skip_link_with_fallback', 1 );
Adding Multiple Skip Links
Some sites benefit from multiple targets:
function add_multiple_skip_links() {
if ( is_admin() ) {
return;
}
?>
<nav class="skip-links" aria-label="Skip links">
<a class="skip-link" href="#main-content">Skip to content</a>
<a class="skip-link" href="#site-navigation">Skip to navigation</a>
<a class="skip-link" href="#footer">Skip to footer</a>
</nav>
<?php
}
add_action( 'wp_body_open', 'add_multiple_skip_links', 1 );
Testing Your Implementation
- Reload your site
- Press
Tabimmediately - The skip link should appear
- Press
Enter - Focus should move to your main content
Test with actual assistive technology if possible. NVDA (Windows) and VoiceOver (Mac) are free.
Common Mistakes
-
Using
display: noneScreen readers skip it entirely - Wrong target ID Link goes nowhere
- Low contrast colors Fails WCAG
- Missing focus styles Users can't see the link
- z-index too low Hidden behind sticky headers
The Easy Way
If you don't want to maintain custom code, I built Skip Links Generator Pro that handles all edge cases including themes without wp_body_open, automatic ID detection, and customizable styling.
But the code above will work for most themes. The important thing is to have skip links at all.
Resources:
Top comments (0)