Skip to content

Accessibility

Build inclusive interfaces that work for everyone. This guide covers WCAG compliance, keyboard navigation, screen readers, and best practices for accessible design.

Overview

Accessibility ensures that all users, including those with disabilities, can perceive, understand, navigate, and interact with your application. The Everforth Design System is built with WCAG 2.1 AA compliance as a baseline.

Core Principles

Perceivable

Information must be presentable to users in ways they can perceive.

Text Alternatives

Provide text alternatives for non-text content like images, icons, and media.

html
<!-- Good: Descriptive alt text -->
<img src="chart.png" alt="Sales increased 25% in Q4 2024">

<!-- Good: Decorative image -->
<img src="decorative-line.png" alt="" role="presentation">

<!-- Bad: Missing or unhelpful alt -->
<img src="chart.png" alt="image">

Color Contrast

Ensure sufficient contrast between text and background colors.

Content TypeMinimum RatioEverforth Compliance
Normal text4.5:1All colors pass
Large text (18px+)3:1All colors pass
UI components3:1All colors pass

Don't Rely on Color Alone

Use additional indicators like icons, patterns, or text labels.

html
<!-- Good: Color + icon + text -->
<div class="df-alert df-alert--error">
  <svg><!-- error icon --></svg>
  <span>Error: Please fix the issues below</span>
</div>

<!-- Bad: Color only -->
<input style="border-color: red;">

Operable

Users must be able to operate the interface using various input methods.

Keyboard Navigation

All functionality must be available via keyboard.

KeyAction
TabMove to next focusable element
Shift + TabMove to previous focusable element
Enter / SpaceActivate buttons, links, checkboxes
Arrow keysNavigate within components (tabs, menus)
EscapeClose modals, dropdowns, tooltips

Focus Management

Visible focus indicators help keyboard users track their location.

css
/* All Everforth components include focus styles */
.df-button:focus-visible {
  outline: 2px solid var(--df-color-focus-ring);
  outline-offset: 2px;
}

/* Never do this */
*:focus { outline: none; } /* Removes focus indicator */

Skip Links

Allow users to skip repetitive navigation.

html
<body>
  <a href="#main-content" class="df-skip-link">
    Skip to main content
  </a>
  <nav><!-- Navigation --></nav>
  <main id="main-content">
    <!-- Page content -->
  </main>
</body>

Understandable

Content and operation must be understandable.

Clear Labels

Form inputs must have associated labels.

html
<!-- Good: Explicit label -->
<label for="email">Email address</label>
<input type="email" id="email" name="email">

<!-- Good: Implicit label -->
<label>
  Email address
  <input type="email" name="email">
</label>

<!-- Bad: Placeholder only -->
<input type="email" placeholder="Email address">

Error Handling

Identify errors clearly and provide suggestions.

html
<div class="df-form-group df-form-group--error">
  <label for="password">Password</label>
  <input
    type="password"
    id="password"
    aria-describedby="password-error"
    aria-invalid="true"
  >
  <span id="password-error" class="df-form-error">
    Password must be at least 8 characters with one number
  </span>
</div>

Robust

Content must be robust enough to work with assistive technologies.

Semantic HTML

Use the correct HTML elements for their intended purpose.

html
<!-- Good: Semantic elements -->
<nav aria-label="Main navigation">
  <ul>
    <li><a href="/">Home</a></li>
  </ul>
</nav>

<main>
  <article>
    <h1>Article Title</h1>
    <p>Content...</p>
  </article>
</main>

<!-- Bad: Div soup -->
<div class="nav">
  <div class="nav-item" onclick="...">Home</div>
</div>

ARIA Guidelines

Use ARIA (Accessible Rich Internet Applications) to enhance accessibility when HTML semantics aren't sufficient.

ARIA Roles

html
<!-- Landmark roles (prefer semantic HTML) -->
<div role="navigation">...</div>  <!-- Use <nav> instead -->
<div role="main">...</div>        <!-- Use <main> instead -->

<!-- Widget roles -->
<div role="tablist">
  <button role="tab" aria-selected="true">Tab 1</button>
  <button role="tab" aria-selected="false">Tab 2</button>
</div>
<div role="tabpanel">Content</div>

<!-- Live regions -->
<div role="alert">Error message</div>
<div role="status" aria-live="polite">Loading...</div>

ARIA States and Properties

html
<!-- Expanded/collapsed -->
<button aria-expanded="false" aria-controls="menu">Menu</button>
<ul id="menu" hidden>...</ul>

<!-- Selected -->
<li role="option" aria-selected="true">Option 1</li>

<!-- Disabled -->
<button aria-disabled="true">Submit</button>

<!-- Described by -->
<input aria-describedby="help-text">
<span id="help-text">Enter your full name</span>

<!-- Invalid -->
<input aria-invalid="true" aria-errormessage="error-msg">
<span id="error-msg">This field is required</span>

Common ARIA Patterns

Modal Dialog

html
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
>
  <h2 id="modal-title">Confirm Action</h2>
  <!-- content -->
</div>

Tabs

html
<div role="tablist" aria-label="Settings">
  <button
    role="tab"
    aria-selected="true"
    aria-controls="panel-1"
  >General</button>
</div>
<div
  role="tabpanel"
  id="panel-1"
  aria-labelledby="tab-1"
>...</div>

Combobox/Autocomplete

html
<input
  role="combobox"
  aria-expanded="true"
  aria-controls="listbox"
  aria-activedescendant="option-2"
>
<ul role="listbox" id="listbox">
  <li role="option" id="option-1">Option 1</li>
  <li role="option" id="option-2">Option 2</li>
</ul>

Testing Accessibility

Automated Testing

Use tools to catch common issues:

  • axe DevTools - Browser extension for accessibility audits
  • Lighthouse - Built into Chrome DevTools
  • WAVE - Web accessibility evaluation tool
  • eslint-plugin-jsx-a11y - Linting for React projects

Manual Testing

Automated tools catch only ~30% of issues. Always test manually:

  1. Keyboard-only navigation - Unplug your mouse and navigate
  2. Screen reader testing - Use VoiceOver (Mac), NVDA (Windows), or JAWS
  3. Zoom testing - Test at 200% and 400% zoom levels
  4. Color contrast - Check with contrast checker tools
  5. Reduced motion - Test with prefers-reduced-motion

Screen Reader Testing Checklist

Page has a descriptive title
Headings are in logical order (h1, h2, h3...)
Images have appropriate alt text
Form fields have labels
Links make sense out of context
Error messages are announced
Dynamic content updates are announced

Motion and Animation

Respect user preferences for reduced motion:

css
/* Default animation */
.df-modal {
  animation: fadeIn 0.3s ease;
}

/* Reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  .df-modal {
    animation: none;
  }
}
javascript
// Check preference in JavaScript
const prefersReducedMotion = window.matchMedia(
  '(prefers-reduced-motion: reduce)'
).matches;

if (!prefersReducedMotion) {
  // Run animation
}

Resources

Built with care by Everforth