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+).