Skip to content

Accessibility Pitfalls

These Are Legal Liability

Since June 28, 2025, the European Accessibility Act makes these mistakes legally actionable. Fines can reach 100,000 euros or 4% of annual revenue. But beyond the law — these mistakes exclude real people from using the software GE builds.


Pitfall 1: ARIA Overuse

The mistake: Adding ARIA attributes to everything, thinking more ARIA means more accessible.

The reality: The first rule of ARIA is do not use ARIA. Use native HTML elements. They are accessible by default. ARIA is a repair tool for when native HTML is insufficient.

The damage ARIA overuse causes:

Problem Example Consequence
Redundant roles <button role="button"> Confuses some screen readers
Incorrect roles <div role="button"> without keyboard handling Looks like a button, does not act like one
Missing states role="checkbox" without aria-checked Screen reader cannot report state
Conflicting info aria-label="Submit" on a button that says "Send" Screen reader says "Submit" but visual users see "Send"
Overriding semantics <nav role="navigation"> Redundant, but some developers add more

GE prevention:

  • Use native HTML elements first: <button>, <a>, <input>, <select>
  • ARIA is only for custom widgets without native equivalents
  • Code review checks for unnecessary ARIA
  • eslint-plugin-jsx-a11y flags common ARIA mistakes

The decision tree:

Can a native HTML element do this?
├── Yes → Use the native element. No ARIA needed.
└── No → Is there a WAI-ARIA authoring practice for this widget?
    ├── Yes → Follow it exactly.
    └── No → Reconsider the design. If a widget has no established
             pattern, users will not know how to interact with it.

Pitfall 2: "Works with Mouse" Bias

The mistake: Building and testing exclusively with a mouse. If it clicks, it works. Ship it.

Who is excluded:

  • Users with motor disabilities who use keyboards or switches
  • Power users who prefer keyboard navigation
  • Screen reader users who navigate via keyboard
  • Users with temporary injuries (broken arm, RSI)

Common keyboard failures:

Failure Example
Click-only interactions Dropdown opens on hover, no keyboard trigger
Missing focus styles Tab key moves focus but nothing visible changes
Keyboard traps Focus enters a widget and cannot leave
No skip links Keyboard user must tab through 50 nav items on every page
Custom scrolling Mouse wheel works, keyboard scroll does not
Drag-and-drop only No keyboard alternative for reordering

GE prevention:

  • All interactive elements must be keyboard accessible
  • Focus indicators are visible (2px minimum, 3:1 contrast)
  • Manual keyboard testing is part of the review checklist
  • Antje writes keyboard navigation test cases in TDD

Pitfall 3: Color-Only Information

The mistake: Using color as the sole means of conveying information, status, or meaning.

Who is excluded:

  • 8% of men and 0.5% of women have color vision deficiency
  • Users viewing screens in direct sunlight
  • Users on monochrome displays or in high contrast mode
  • Users who have customized their color settings

Common violations:

Violation Fix
Red text = error, black text = valid Add error icon + "Error:" prefix
Green dot = online, red dot = offline Add text label "Online"/"Offline"
Chart with color-coded lines only Add patterns, markers, or labels
Required fields marked with red asterisk only Add "(required)" text
Links distinguished by color only Add underline or other visual indicator

GE prevention:

  • Color is always paired with text, icons, or patterns
  • Alexander's design system enforces this at the component level
  • Automated contrast checking in CI/CD
  • Manual review includes grayscale check

The mistake: No mechanism to skip repetitive navigation content.

The impact: A keyboard or screen reader user must tab through the entire navigation menu on every single page before reaching the main content. On a site with 20 navigation links, that is 20 tab presses before they can read anything.

GE prevention:

<!-- First focusable element on the page -->
<a href="#main-content" class="skip-link">Skip to main content</a>

<!-- Navigation here -->

<main id="main-content">
  <!-- Page content -->
</main>

Skip links are visually hidden by default but become visible on focus. They are the first element in the tab order.

For complex pages, multiple skip links may be needed:

<a href="#main-content" class="skip-link">Skip to main content</a>
<a href="#search" class="skip-link">Skip to search</a>
<a href="#footer" class="skip-link">Skip to footer</a>

Pitfall 5: Custom Components Without Keyboard Support

The mistake: Building custom UI components (dropdowns, modals, tabs, date pickers, carousels) that only work with a mouse.

Why it happens: Native HTML form elements look plain. Designers want custom styling. Developers rebuild from <div> elements. The rebuilt component looks right but loses all native accessibility.

What native elements provide for free:

Feature Native Custom (must implement yourself)
Keyboard navigation Built-in Must handle keyDown events
Focus management Built-in Must manage tabindex
Screen reader support Built-in Must add ARIA roles and states
Form validation Built-in Must implement and announce
Touch support Built-in Must handle touch events

GE prevention:

  • Prefer native elements with CSS styling
  • When custom components are necessary, follow WAI-ARIA Authoring Practices exactly
  • Every custom component must handle: Tab, Shift+Tab, Enter, Space, Escape, Arrow keys (as appropriate for the widget type)
  • Antje writes keyboard interaction tests before implementation

Pitfall 6: "We Will Add Accessibility Later"

The mistake: Building the feature first, planning to add accessibility in a future sprint.

Why it never works:

  1. Accessibility retrofitting costs 10-100x more than building accessible
  2. The backlog grows faster than the remediation capacity
  3. Structural issues (wrong HTML elements, missing landmarks) require rewriting, not patching
  4. "Later" never comes — there is always a higher-priority feature

The math:

Build accessible from line 1:    +10% effort during development
Retrofit accessibility after:    +100-500% effort, plus rewrite risk
Fix after a lawsuit:             Unlimited effort, plus legal costs

GE prevention:

  • Accessibility is in the definition of done
  • An inaccessible feature does not pass code review
  • There is no "accessibility sprint" because every sprint includes accessibility
  • Julian blocks deployment if WCAG AA is not met

Pitfall 7: Testing Only with Automated Tools

The mistake: Running axe-core or Lighthouse, getting a passing score, and declaring the site accessible.

What automated tools catch (~30-40%):

  • Missing alt text
  • Low color contrast
  • Missing form labels
  • Invalid ARIA attributes
  • Missing document language
  • Duplicate IDs

What automated tools miss (~60-70%):

  • Logical tab order (tools cannot know what is "logical")
  • Meaningful alt text (tools check existence, not quality)
  • Keyboard traps (require interaction to detect)
  • Focus management in dynamic content
  • Screen reader announcement quality
  • Cognitive accessibility (is the content understandable?)
  • Touch target adequacy in real-world context
  • Content reflow at 200% zoom
  • Context-appropriate ARIA usage

GE prevention:

  • Automated testing is the baseline, not the standard
  • Manual keyboard testing on every feature
  • Screen reader testing on key user flows
  • Marta and Iwona verify accessibility in code review
  • Quarterly manual accessibility audit on production

The 100% Lighthouse score trap:

A Lighthouse accessibility score of 100 means the automated checks passed. It does not mean the site is accessible. Lighthouse tests approximately 50 rules. WCAG 2.2 AA has 86 success criteria, many of which require human judgment.


Pitfall 8: Focus Management in SPAs

The mistake: In single-page applications, when navigation changes the view without a page reload, focus stays on the element that triggered the navigation. The user does not know the content has changed.

The problem: In a traditional multi-page site, a new page load resets focus to the top. Screen readers announce the new page title. SPAs break this contract.

Common SPA focus failures:

Scenario Failure Fix
Route change Focus stays on nav link Move focus to main heading or use aria-live
Content loaded New content appears, focus unchanged Announce with aria-live="polite"
Item deleted Focus lost (element gone) Move focus to next item or parent
Modal opened Focus stays behind modal Move focus to modal, trap within
Infinite scroll New items load, no announcement Announce "X more items loaded"
Form submission Success message appears off-screen Move focus to success message or use alert role

GE prevention:

  • SPA routing includes focus management
  • Route changes move focus to the main heading (<h1>)
  • Dynamic content updates use aria-live regions
  • Deleting items moves focus to a predictable location
  • All modals trap focus and restore on close

Implementation pattern:

// On route change in SPA
useEffect(() => {
  const mainHeading = document.querySelector('h1');
  if (mainHeading) {
    mainHeading.setAttribute('tabindex', '-1');
    mainHeading.focus();
  }
  // Announce page title to screen readers
  document.title = `${pageTitle} | App Name`;
}, [location]);

Pitfall 9: Inaccessible Error Handling

The mistake: Displaying error messages that are only visible (not announced) or only indicated by color change.

Common error handling failures:

Failure Impact
Error shown above form, not linked to field Screen reader user does not know which field has error
Error shown only as red border Color-blind users do not see the error
Error disappears after timeout Slow readers miss the message
Validation on blur only Keyboard-only users miss errors on previous fields
Error summary not focusable Screen reader users cannot find the error list

GE prevention:

<!-- Error summary at top of form, focusable -->
<div role="alert" tabindex="-1" id="error-summary">
  <h2>There are 2 errors in this form</h2>
  <ul>
    <li><a href="#email">Email address is required</a></li>
    <li><a href="#password">Password must be at least 8 characters</a></li>
  </ul>
</div>

<!-- Inline error linked to field -->
<label for="email">Email address</label>
<input
  id="email"
  type="email"
  aria-invalid="true"
  aria-describedby="email-error"
/>
<p id="email-error" class="error">
  <span aria-hidden="true">&#x26A0;</span>
  Email address is required
</p>

Pitfall 10: Accessibility Overlays

The mistake: Installing a JavaScript overlay widget (AccessiBe, UserWay, AudioEye, etc.) instead of fixing the underlying code.

Why overlays fail:

  • They do not fix the source code — they add a broken layer on top
  • They can interfere with real assistive technology
  • They have been cited in ADA lawsuits as insufficient
  • They can break existing accessible features
  • They create a false sense of compliance
  • The National Federation of the Blind has publicly opposed overlays

GE position: Overlays are never used. Accessibility is built into the code. There are no shortcuts.


Quick Reference: Agent Checklist

Before submitting code with UI components:

  • [ ] Semantic HTML used (not divs as buttons or spans as links)
  • [ ] ARIA used only when native HTML is insufficient
  • [ ] All interactive elements keyboard accessible
  • [ ] Focus indicators visible (2px minimum, 3:1 contrast)
  • [ ] Color is not the only means of conveying information
  • [ ] Form fields have visible labels (not just placeholders)
  • [ ] Error messages linked to fields and announced
  • [ ] Images have appropriate alt text
  • [ ] Dynamic content changes announced to screen readers
  • [ ] Skip links present
  • [ ] axe-core test included for new components
  • [ ] Manually tested with keyboard navigation

Further Reading