Semantic HTML, ARIA landmarks, keyboard navigation, skip links, color contrast, and screen reader testing — the accessibility checklist for every theme.
Accessibility Is Not Optional
Web accessibility means people with disabilities can use your website. That includes people who are blind (screen readers), have low vision (magnification, high contrast), have motor disabilities (keyboard-only navigation), or are deaf (captions). In many countries, accessibility is legally required for public-facing websites.
Every JekCMS theme is built with WCAG 2.1 Level AA compliance as a baseline. Here are the specific techniques we use.
Semantic HTML Structure
The foundation of accessibility is semantic HTML. Screen readers rely on HTML elements to understand page structure:
<header role="banner">...</header>
<nav role="navigation" aria-label="Main navigation">...</nav>
<main role="main">
<article>
<h1>Post Title</h1>
<p>Content...</p>
</article>
<aside role="complementary">Sidebar</aside>
</main>
<footer role="contentinfo">...</footer>
Every page uses <header>, <nav>, <main>, <article>, <aside>, and <footer>. ARIA roles are added as fallbacks for older assistive technology.
Skip Navigation
Keyboard users should not have to tab through the entire header and navigation to reach the main content. A skip link is the first focusable element on the page:
<a href="#main-content" class="skip-link">Skip to main content</a>
.skip-link {
position: absolute;
top: -40px;
left: 0;
padding: 8px 16px;
background: var(--primary);
color: white;
z-index: 1000;
}
.skip-link:focus {
top: 0;
}
Keyboard Navigation
Every interactive element must be reachable and operable with keyboard alone. That means: all links and buttons have visible focus indicators, dropdown menus open with Enter/Space and navigate with arrow keys, modals trap focus (Tab cycles within the modal until Escape closes it).
// Focus trap for modals
function trapFocus(modal) {
const focusable = modal.querySelectorAll(
'a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const first = focusable[0];
const last = focusable[focusable.length - 1];
modal.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
if (e.key === 'Escape') closeModal(modal);
});
}
Color Contrast
WCAG AA requires a minimum contrast ratio of 4.5:1 for normal text and 3:1 for large text. Our CSS custom properties are designed to meet these ratios in both light and dark modes:
- Light mode: #1a1a1a on #ffffff = 16.5:1 ratio
- Dark mode: #e6edf3 on #0d1117 = 13.2:1 ratio
- Links: #0969da on #ffffff = 5.7:1 ratio (meets AA)
Image Alt Text
Every <img> tag in JekCMS requires an alt attribute. The media upload form includes an alt text field that is required before saving. Decorative images use alt="" (empty alt) to be skipped by screen readers.
Form Accessibility
Every form input has an associated <label> element. Error messages are announced to screen readers using aria-live="polite". Required fields are marked with aria-required="true".
Testing
We test with: keyboard navigation (Tab through entire page), screen reader (NVDA on Windows), browser extensions (axe DevTools, WAVE), and Lighthouse accessibility audit (target score: 95+).