Skip to main content

Accessibility Standards

Accessibility is not a separate "polish" step. It is part of quality markup: semantic structure, keyboard navigation, clear focus states, and readable contrast. GeneratePress gives you a good starting point, but custom layouts (Elements + blocks + custom CSS/JS) can easily break the experience.

The Practical Standards That Matter Most

You do not need to memorize WCAG to build accessible pages. Focus on these recurring themes:

  • Structure: headings + landmarks make a page understandable
  • Operation: everything works with a keyboard
  • Perception: contrast, readable typography, visible focus
  • Robustness: controls are real HTML elements, not divs
caution

Never remove focus outlines globally (for example, *:focus { outline: none; }). If you restyle focus, replace it with something equally visible.

Landmarks and Template Structure

Accessibility gets dramatically easier when each template follows a predictable shape.

LandmarkPurposeWhat to ensure
headerBranding + primary navigationOne primary navigation region, consistent across the site
navNavigationUses real links; dropdowns work with keyboard
mainPrimary contentExactly one main per page; contains the primary page heading
footerSecondary contentHelpful links, but not a duplicate of the entire header nav
note

If you replace the header/footer with custom Elements or block templates, re-check landmarks and keyboard order. Most regressions come from "pretty" layouts built with generic containers.

Keyboard Navigation: What to Test

Use this simple keyboard test on a few key templates (home, page, blog post, archive):

  • Tab reaches navigation and primary calls-to-action
  • Enter activates links/buttons
  • Dropdown menus can be opened and navigated
  • Focus order matches the visual order
flowchart LR
A[Skip link] --> B[Primary nav]
B --> C[Search / utilities]
C --> D[Main content]
D --> E[Sidebar widgets]
E --> F[Footer links]

A skip link lets keyboard and screen reader users jump straight to main content.

If your theme already includes one, do not duplicate it. If it does not, adding it via wp_body_open is a stable, theme-agnostic approach.

Child theme: add a skip link via wp_body_open
<?php
add_action( 'wp_body_open', function () {
echo '<a class="skip-link screen-reader-text" href="#content">Skip to main content</a>';
} );

Then ensure your main content container has an id you can target (many themes use #content already). If not, add an id via a Hook Element near the main wrapper, or adjust the skip link target.

If you need a reliable focus target, you can add a small anchor element near the start of main content:

Hook Element: add a focus target for skip links (example)
<?php
echo '<div id="content" tabindex="-1"></div>';
caution

Use tabindex="-1" only for a skip link destination (a programmatic focus target). Do not add positive tabindex values to "fix" focus order.

Improve Focus Styling Without Breaking Design

GeneratePress styles are intentionally minimal; your custom CSS should make focus visible.

CSS: visible focus ring (safe default)
:root {
--focus-ring: 3px solid #0b57d0;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
outline: var(--focus-ring);
outline-offset: 2px;
}
tip

Use :focus-visible instead of :focus so mouse users don't see persistent rings after clicks.

Common GeneratePress Customization Pitfalls

ChangeWhat can breakSafer approach
Custom header built with blocksMissing landmark roles, broken focus orderKeep header + nav semantics; test with keyboard
Off-canvas menusFocus trapped behind overlayEnsure focus moves into the menu and can return
Fancy buttons as divsNot keyboard-operableUse <a> or <button> with correct attributes
Icon-only linksScreen readers get no labelAdd text or aria-label that describes action
Color-only statesUsers can't perceive meaningAdd underlines, icons, or text changes

ARIA: Use It Sparingly

Native elements usually beat custom elements.

GoalPreferAvoid
Click action<button>div with role="button"
Navigation<a href>JS-only click handlers
Expand/collapse<button aria-expanded>Hiding/showing content with no state exposure
tip

If you are adding ARIA to compensate for a missing semantic element, consider replacing the element instead.

Motion and Reduced Motion

If you add animation or smooth scrolling, respect the user's reduced motion preference.

CSS: reduce motion when requested
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
scroll-behavior: auto !important;
}
}

Quick Testing Toolkit

You can do meaningful testing without expensive tools:

  • Keyboard-only walkthrough (Tab/Shift+Tab/Enter/Escape)
  • Browser accessibility tree inspection
  • Lighthouse accessibility audit (as a starting signal, not a final verdict)

On a server, you can at least spot obvious missing alt attributes:

Spot-check for images without alt (quick heuristic)
PAGE_URL="https://example.com/"
curl -sL "$PAGE_URL" | rg -n "<img(?![^>]*\salt=)" || true

Hands-On: Accessibility QA on One Template

Pick one template (home page is a good start) and run this checklist:

  1. Tab from the top: does a skip link appear?
  2. Can you reach the primary CTA and activate it?
  3. Can you open/close the menu and keep focus within it?
  4. Is the focus indicator always visible?
  5. Do icon-only links have labels?

If you find a problem, fix it once in a shared component (Element, header layout, global CSS) rather than patching individual pages.

If your site has forms (contact, newsletter, checkout), add a quick form pass:

  • Inputs have visible labels (not placeholder-only)
  • Errors are announced and not color-only
  • Focus moves to the first invalid field on submit

Troubleshooting

SymptomLikely causeFix
Focus disappearsOutline removed in CSSRemove the rule, or add a :focus-visible ring
Menu unusable with keyboardCustom JS menu behaviorUse theme menu, or implement proper ARIA + focus handling
Screen reader reads "link" with no contextIcon-only controlsAdd visible text or aria-label
Skip link goes nowhereWrong id targetMatch skip link href to main content id
Animations feel overwhelmingNo reduced-motion supportAdd prefers-reduced-motion overrides

Quick Reference

  • Use semantic HTML and real controls
  • Always keep a visible focus state
  • Test with keyboard on every major template
  • Prefer native elements over ARIA workarounds

What's Next