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
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.
| Landmark | Purpose | What to ensure |
|---|---|---|
header | Branding + primary navigation | One primary navigation region, consistent across the site |
nav | Navigation | Uses real links; dropdowns work with keyboard |
main | Primary content | Exactly one main per page; contains the primary page heading |
footer | Secondary content | Helpful links, but not a duplicate of the entire header nav |
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):
Tabreaches navigation and primary calls-to-actionEnteractivates 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]
Add a Skip Link (Theme-Safe)
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.
<?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:
<?php
echo '<div id="content" tabindex="-1"></div>';
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.
: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;
}
Use :focus-visible instead of :focus so mouse users don't see persistent rings after clicks.
Common GeneratePress Customization Pitfalls
| Change | What can break | Safer approach |
|---|---|---|
| Custom header built with blocks | Missing landmark roles, broken focus order | Keep header + nav semantics; test with keyboard |
| Off-canvas menus | Focus trapped behind overlay | Ensure focus moves into the menu and can return |
| Fancy buttons as divs | Not keyboard-operable | Use <a> or <button> with correct attributes |
| Icon-only links | Screen readers get no label | Add text or aria-label that describes action |
| Color-only states | Users can't perceive meaning | Add underlines, icons, or text changes |
ARIA: Use It Sparingly
Native elements usually beat custom elements.
| Goal | Prefer | Avoid |
|---|---|---|
| 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 |
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.
@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:
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:
- Tab from the top: does a skip link appear?
- Can you reach the primary CTA and activate it?
- Can you open/close the menu and keep focus within it?
- Is the focus indicator always visible?
- 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
| Symptom | Likely cause | Fix |
|---|---|---|
| Focus disappears | Outline removed in CSS | Remove the rule, or add a :focus-visible ring |
| Menu unusable with keyboard | Custom JS menu behavior | Use theme menu, or implement proper ARIA + focus handling |
| Screen reader reads "link" with no context | Icon-only controls | Add visible text or aria-label |
| Skip link goes nowhere | Wrong id target | Match skip link href to main content id |
| Animations feel overwhelming | No reduced-motion support | Add 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
- Next: Performance-SEO Link