DevToolBoxZA DARMO
Blog

Web Accessibility Guide: WCAG 2.2, ARIA, Keyboard Navigation, Screen Readers, and Testing

17 min readby DevToolBox
TL;DR: Use semantic HTML as your foundation, add ARIA only when native elements fall short, ensure 4.5:1 color contrast, support full keyboard navigation with visible focus indicators, label all form inputs, provide meaningful alt text, and test with axe-core plus real screen readers. WCAG 2.2 AA is the legal baseline for most jurisdictions.

Key Takeaways

  • Semantic HTML provides 80% of accessibility for free — use native elements before reaching for ARIA.
  • WCAG 2.2 introduces new success criteria for focus appearance, dragging alternatives, and target size.
  • Color contrast ratios must be at least 4.5:1 for normal text and 3:1 for large text (AA level).
  • Every interactive element must be keyboard accessible with a visible focus indicator.
  • Forms need associated labels, clear error messages, and programmatic validation announcements.
  • Test with automated tools (axe, Lighthouse) AND manual testing with screen readers (NVDA, VoiceOver).

Web accessibility ensures that websites and applications are usable by everyone, including people with visual, auditory, motor, or cognitive disabilities. With over 1.3 billion people worldwide living with some form of disability, accessibility is not just a legal requirement — it is a moral imperative and a business advantage. This guide covers WCAG 2.2 conformance levels, semantic HTML, ARIA attributes, keyboard navigation, screen reader optimization, and testing strategies with practical code examples.

1. WCAG 2.2 Guidelines & Conformance Levels

The Web Content Accessibility Guidelines (WCAG) 2.2, published by the W3C in October 2023, is the current standard for web accessibility. It builds on WCAG 2.1 with nine new success criteria focused on users with cognitive disabilities, low vision, and mobile device users. WCAG is organized around four principles known as POUR: Perceivable, Operable, Understandable, and Robust.

WCAG defines three conformance levels. Level A covers the minimum baseline — without these, content is fundamentally inaccessible. Level AA is the standard target for most organizations and is referenced by most accessibility laws. Level AAA represents the highest level of accessibility but is not required as a general policy because some content cannot satisfy all AAA criteria.

LevelCriteria CountTarget AudienceLegal Requirement
A30Minimum baselineRequired everywhere
AA24Standard targetADA, Section 508, EAA
AAA33Enhanced accessibilityNot generally required

New in WCAG 2.2: Focus Not Obscured (AA) ensures focused elements are at least partially visible. Dragging Movements (AA) requires alternatives for drag interactions. Target Size Minimum (AA) sets 24x24 CSS pixel minimum for pointer targets. Consistent Help (A) mandates help mechanisms appear in the same relative order. Redundant Entry (A) prevents users from re-entering previously submitted information.

2. Semantic HTML Elements & Landmarks

Semantic HTML is the foundation of accessible web development. Native HTML elements carry implicit roles, states, and keyboard behaviors that assistive technologies understand without additional ARIA attributes. A button element is focusable, activatable with Enter and Space, and announced as a button — a div with an onclick handler provides none of these behaviors automatically.

Semantic vs Non-Semantic HTML

<!-- BAD: Non-semantic (inaccessible) -->
<div class="header">
  <div class="nav">
    <div onclick="navigate('/home')">Home</div>
    <div onclick="navigate('/about')">About</div>
  </div>
</div>
<div class="main">
  <div class="title">Page Title</div>
  <div class="btn" onclick="submit()">Submit</div>
</div>

<!-- GOOD: Semantic (accessible) -->
<header>
  <nav aria-label="Main navigation">
    <a href="/home">Home</a>
    <a href="/about">About</a>
  </nav>
</header>
<main>
  <h1>Page Title</h1>
  <button type="submit">Submit</button>
</main>

HTML5 landmark elements map directly to ARIA landmark roles and help screen reader users navigate the page structure. The header element maps to role banner, nav to role navigation, main to role main, aside to role complementary, and footer to role contentinfo. Screen readers provide shortcuts to jump between landmarks, making proper use of these elements critical for efficient navigation.

HTML ElementARIA Landmark RolePurpose
<header>bannerSite-wide header content
<nav>navigationNavigation links
<main>mainPrimary page content
<aside>complementarySupporting content
<footer>contentinfoSite-wide footer content
<section>region (with label)Thematic grouping
<form>form (with label)User input form

Heading hierarchy communicates document structure. Start with a single h1 per page, then use h2 through h6 in sequential order without skipping levels. Screen reader users often scan pages by heading level — 67.5% of screen reader users report using headings as their primary navigation method according to the WebAIM survey.

3. ARIA Roles, States & Properties

Accessible Rich Internet Applications (ARIA) provides attributes that define the role, state, and properties of elements when native HTML semantics are insufficient. The first rule of ARIA is: do not use ARIA if a native HTML element with equivalent semantics exists. ARIA overrides or supplements native semantics but does not change element behavior — adding role button to a div does not make it focusable or keyboard-interactive.

ARIA Tab Interface Example

<!-- Accessible tab component with ARIA -->
<div role="tablist" aria-label="Product info">
  <button role="tab"
    id="tab-details"
    aria-selected="true"
    aria-controls="panel-details"
    tabindex="0">Details</button>
  <button role="tab"
    id="tab-reviews"
    aria-selected="false"
    aria-controls="panel-reviews"
    tabindex="-1">Reviews</button>
  <button role="tab"
    id="tab-shipping"
    aria-selected="false"
    aria-controls="panel-shipping"
    tabindex="-1">Shipping</button>
</div>

<div role="tabpanel"
  id="panel-details"
  aria-labelledby="tab-details"
  tabindex="0">
  <p>Product details content here.</p>
</div>

<!-- Keyboard: Arrow keys between tabs,
     Tab key moves into active panel -->

ARIA roles fall into six categories: landmark roles (banner, navigation, main), widget roles (button, tab, dialog, slider), document structure roles (article, heading, list), live region roles (alert, status, log, timer), window roles (dialog, alertdialog), and abstract roles (never use these directly). Common widget roles include tablist/tab/tabpanel for tab interfaces and menu/menuitem for application menus.

ARIA states and properties communicate dynamic information. aria-expanded indicates whether a collapsible section is open. aria-selected marks the active tab. aria-live announces dynamic content updates to screen readers — use polite for non-urgent updates and assertive for critical alerts. aria-describedby links elements to additional descriptive text, such as form field instructions or error messages.

aria-live Regions

<!-- Status message (polite) -->
<div aria-live="polite" aria-atomic="true">
  3 results found for "accessibility"
</div>

<!-- Error alert (assertive) -->
<div role="alert">
  <!-- role="alert" implies assertive -->
  Payment failed. Check your card details.
</div>

<!-- Progress update -->
<div role="status">
  <!-- role="status" implies polite -->
  Uploading: 67% complete
</div>

4. Keyboard Navigation & Focus Management

All interactive elements must be operable with a keyboard alone. Native interactive elements (a, button, input, select, textarea) are in the tab order by default. Custom interactive elements need tabindex 0 to be added to the natural tab order. Never use tabindex values greater than 0 as they disrupt the natural tab sequence and create a confusing navigation experience.

KeyActionElement Type
TabMove to next focusable elementAll interactive
Shift + TabMove to previous elementAll interactive
EnterActivate link or buttonLinks, buttons
SpaceToggle button/checkboxButtons, checkboxes
EscapeClose dialog or dropdownModals, menus
Arrow keysNavigate within widgetTabs, menus, radios

Focus management is critical for single-page applications and dynamic content. When content changes (route transitions, modal dialogs, form submissions), programmatically move focus to the new content or announcement. Use tabindex negative one to make elements programmatically focusable without adding them to the tab order. Focus trapping in modals prevents keyboard users from tabbing behind the dialog overlay.

Focus Trap for Modal Dialog

function trapFocus(dialog) {
  const focusable = dialog.querySelectorAll(
    'button, [href], input, select,' +
    ' textarea, [tabindex]:not([tabindex="-1"])'
  );
  const first = focusable[0];
  const last = focusable[focusable.length - 1];

  dialog.addEventListener('keydown', (e) => {
    if (e.key !== 'Tab') return;

    if (e.shiftKey) {
      if (document.activeElement === first) {
        e.preventDefault();
        last.focus();
      }
    } else {
      if (document.activeElement === last) {
        e.preventDefault();
        first.focus();
      }
    }
  });

  first.focus();
}

A visible focus indicator is required by WCAG 2.2 Focus Appearance (AA). The default browser outline must not be removed without a custom replacement. Focus indicators should have at least a 2px solid outline with a 3:1 contrast ratio against adjacent colors. Consider using :focus-visible instead of :focus to show focus styles only for keyboard navigation, not mouse clicks.

Focus Indicator CSS

/* Custom focus indicator (WCAG 2.2) */
:focus-visible {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
  border-radius: 2px;
}

/* High contrast for dark backgrounds */
.dark-section :focus-visible {
  outline: 2px solid #fbbf24;
  outline-offset: 2px;
}

5. Screen Reader Optimization

Screen readers translate visual content into speech or braille output. Major screen readers include NVDA (free, Windows), JAWS (commercial, Windows), VoiceOver (built-in, macOS/iOS), and TalkBack (built-in, Android). Each has different interaction modes — NVDA and JAWS use browse mode for reading content and forms/focus mode for interactive elements.

Screen readers announce elements based on their role, name, and state. The accessible name is computed from: content (text inside the element), associated label, aria-label, aria-labelledby, title attribute, or alt attribute. The aria-labelledby attribute takes the highest priority and can reference multiple elements by their IDs. Always ensure every interactive element has an accessible name.

Visually Hidden (Screen Reader Only)

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Usage: visible to screen readers only */
<button>
  <svg aria-hidden="true"><!-- icon --></svg>
  <span class="sr-only">Close dialog</span>
</button>

Live regions notify screen readers about dynamic content changes without moving focus. Add aria-live to a container before content changes. The polite value waits for the user to finish their current action before announcing. The assertive value interrupts immediately and should only be used for critical information like error alerts. For status messages, use role status which implies aria-live polite.

6. Color Contrast & Visual Accessibility

WCAG 2.2 requires a minimum contrast ratio of 4.5:1 for normal text (under 18pt or 14pt bold) and 3:1 for large text (18pt+ or 14pt+ bold) at Level AA. Level AAA raises these to 7:1 and 4.5:1 respectively. Non-text elements like icons, borders, and focus indicators need at least 3:1 contrast against adjacent colors.

WCAG LevelNormal TextLarge TextUI Components
AA (required)4.5:13:13:1
AAA (enhanced)7:14.5:1N/A

Never rely on color alone to convey information. Links within text need an additional visual indicator beyond color — an underline is the most recognizable. Form validation errors should combine a red color with an icon and text message. Charts and graphs should use patterns or labels in addition to colors to distinguish data series.

Support user preferences with CSS media queries. The prefers-reduced-motion media query allows you to disable or reduce animations for users with vestibular disorders. The prefers-contrast media query lets you increase contrast for users who need it. The prefers-color-scheme query supports dark mode, which many low-vision users prefer.

Respecting User Preferences

/* Reduce or disable animations */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Increase contrast when requested */
@media (prefers-contrast: more) {
  :root {
    --text-color: #000000;
    --bg-color: #ffffff;
    --border-color: #000000;
  }
}

/* Dark mode support */
@media (prefers-color-scheme: dark) {
  :root {
    --text-color: #f1f5f9;
    --bg-color: #0f172a;
  }
}

7. Form Accessibility

Every form input must have a programmatically associated label. Use the label element with a for attribute matching the input id, or wrap the input inside the label element. Placeholder text is not a substitute for labels — it disappears when the user types, has low contrast by default, and is not universally supported by assistive technologies.

Accessible Form Example

<form novalidate>
  <fieldset>
    <legend>Contact Information</legend>

    <label for="email">Email address</label>
    <input
      type="email"
      id="email"
      name="email"
      required
      aria-describedby="email-hint email-error"
      aria-invalid="false"
    />
    <span id="email-hint">
      We will never share your email.
    </span>
    <span id="email-error" role="alert"></span>
  </fieldset>

  <fieldset>
    <legend>Preferred contact method</legend>
    <label>
      <input type="radio" name="contact"
        value="email" /> Email
    </label>
    <label>
      <input type="radio" name="contact"
        value="phone" /> Phone
    </label>
  </fieldset>

  <button type="submit">Send message</button>
</form>

Group related fields with fieldset and legend elements. Radio buttons and checkboxes within a group should share a fieldset with a descriptive legend. This gives screen reader users context about what the group represents. For complex forms, use aria-describedby to link instructions and help text to their corresponding inputs.

Accessible error handling requires three things: identify the field in error, describe the error clearly, and help the user fix it. Use aria-invalid true on erroneous fields, associate error messages with aria-describedby, and use aria-live or role alert for dynamically displayed errors. Move focus to the first error field on form submission to guide users to the problem.

Error Handling Pattern

function handleSubmit(form) {
  const errors = validate(form);
  if (errors.length === 0) return true;

  // Clear previous errors
  form.querySelectorAll('[aria-invalid]').forEach(
    el => el.setAttribute('aria-invalid', 'false')
  );

  // Mark fields with errors
  errors.forEach(({ fieldId, message }) => {
    const field = document.getElementById(fieldId);
    const errorEl = document.getElementById(
      fieldId + '-error'
    );
    field.setAttribute('aria-invalid', 'true');
    errorEl.textContent = message;
  });

  // Focus first error field
  document.getElementById(
    errors[0].fieldId
  ).focus();
  return false;
}

8. Image Alt Text Best Practices

All images must have an alt attribute. Informative images need descriptive alt text that conveys the same information the image provides visually. Decorative images should have an empty alt attribute (alt equals empty string) so screen readers skip them entirely. Never omit the alt attribute — this causes screen readers to announce the file name.

Write effective alt text by describing the content and function, not the appearance. Keep it concise (typically under 125 characters). For complex images like charts or infographics, provide a brief alt text summary and a longer description via aria-describedby or a nearby text element. Background images added via CSS should have their text equivalent in the HTML.

Image TypeAlt Text ApproachExample
InformativeDescribe content/functionalt="Bar chart: 40% Q4 revenue increase"
DecorativeEmpty alt attributealt=""
Linked imageDescribe destinationalt="Company Name - Homepage"
Icon buttonDescribe actionalt="Search" (not "Magnifying glass")
Complex chartBrief summary + long descalt="Q4 sales" + aria-describedby
Text in imageReproduce the textalt="50% OFF Summer Sale"

Icon buttons and linked images need alt text that describes the action or destination, not the icon appearance. A search icon button should have alt text like Search, not Magnifying glass. Linked logos should describe the destination: Company Name Home Page. SVG icons should use role img with an aria-label or include a title element inside the SVG.

<!-- SVG icon with accessibility -->
<button>
  <svg role="img" aria-label="Delete item"
    viewBox="0 0 24 24">
    <title>Delete item</title>
    <path d="M6 19c0 1.1.9 2 2 2h8..." />
  </svg>
</button>

<!-- Decorative SVG (hidden from AT) -->
<svg aria-hidden="true" focusable="false">
  <use href="#decorative-divider" />
</svg>

9. Responsive & Mobile Accessibility

WCAG 2.2 requires content to be usable at 320 CSS pixels width without horizontal scrolling (reflow criterion). Text must be resizable up to 200% without loss of content or functionality. Use relative units (rem, em, percentages) instead of fixed pixels for text sizing. Viewport meta tags should not disable user scaling — never use maximum-scale=1 or user-scalable=no.

Touch targets should be at least 44x44 CSS pixels for comfortable use, with a 24x24 minimum per WCAG 2.2. Provide adequate spacing between targets to prevent accidental taps. Gestures that require complex paths (swipe, pinch) must have simple alternatives (buttons, links). Orientation should not be locked unless essential for the application.

<!-- BAD: Prevents user from zooming -->
<meta name="viewport"
  content="width=device-width,
  initial-scale=1, maximum-scale=1,
  user-scalable=no" />

<!-- GOOD: Allows user zoom -->
<meta name="viewport"
  content="width=device-width,
  initial-scale=1" />

/* Touch target sizing */
.touch-target {
  min-width: 44px;
  min-height: 44px;
  padding: 12px;
}

/* Ensure text reflows at 320px */
.content {
  max-width: 100%;
  overflow-wrap: break-word;
}

Mobile screen readers use touch-based gestures instead of keyboard shortcuts. VoiceOver users swipe left and right to navigate elements, double-tap to activate, and use the rotor for heading and landmark navigation. Ensure all custom components work with these touch gestures. Use native HTML form controls whenever possible as they have the best mobile accessibility support.

10. Accessible Tables & Data Visualization

Data tables need proper header markup for screen readers to announce cell context. Use th elements with scope attribute (col or row) to associate headers with cells. Complex tables with multi-level headers should use the id and headers attributes to create explicit associations. Add a caption element or aria-label to describe the table purpose.

Accessible Data Table

<table>
  <caption>
    Quarterly Revenue (USD millions)
  </caption>
  <thead>
    <tr>
      <th scope="col">Quarter</th>
      <th scope="col">Revenue</th>
      <th scope="col">Growth</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Q1 2025</th>
      <td>12.4</td>
      <td>+8%</td>
    </tr>
    <tr>
      <th scope="row">Q2 2025</th>
      <td>14.1</td>
      <td>+13.7%</td>
    </tr>
  </tbody>
</table>

Never use tables for layout — use CSS Grid or Flexbox instead. Layout tables confuse screen readers by implying data relationships where none exist. If you must use a table for layout, add role presentation to strip the table semantics. Data tables should include a summary of data trends or provide alternative text representations for screen reader users.

Charts and data visualizations should provide text alternatives. Use aria-label on SVG chart containers. Include a data table as an alternative view that screen readers can access. For interactive charts, ensure keyboard navigation of data points with aria-roledescription and accessible tooltips. Consider using aria-live regions to announce data changes in real-time dashboards.

11. Testing with axe, Lighthouse & Screen Readers

Automated testing catches about 30-50% of accessibility issues. Use axe-core (via browser extension or CI integration) as the primary automated testing tool — it has zero false positives and covers WCAG 2.2 criteria. Lighthouse accessibility audit in Chrome DevTools provides a quick overview. pa11y and Tenon are additional CLI-based options for CI pipelines.

Automated Testing with axe-core

// axe-core in Cypress E2E tests
describe('Accessibility', () => {
  it('has no a11y violations', () => {
    cy.visit('/');
    cy.injectAxe();
    cy.checkA11y(null, {
      runOnly: {
        type: 'tag',
        values: ['wcag2a', 'wcag2aa',
          'wcag22aa']
      }
    });
  });
});

// axe-core in Jest unit tests
import { axe, toHaveNoViolations }
  from 'jest-axe';
expect.extend(toHaveNoViolations);

test('form is accessible', async () => {
  const { container } = render(<LoginForm />);
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

Manual testing is essential for catching issues automated tools miss. Test keyboard navigation by using only Tab, Shift+Tab, Enter, Space, Escape, and Arrow keys. Verify focus order is logical and focus indicators are visible. Test with at least one screen reader — VoiceOver on macOS or NVDA on Windows are both free. Check that all interactive elements are announced with correct roles and names.

Build accessibility into your development workflow. Run axe checks in your CI pipeline to catch regressions. Include accessibility acceptance criteria in user stories. Conduct regular audits with real users who use assistive technologies. Use the accessibility tree in Chrome DevTools (Elements panel) to inspect how the browser exposes elements to assistive technologies.

ToolTypePlatformBest For
axe DevToolsExtensionChrome/FirefoxQuick page audits
axe-coreCI/CD libNode.jsRegression testing
LighthouseBuilt-inChrome DevToolsQuick audit scores
NVDAScreen readerWindows (free)Manual SR testing
VoiceOverScreen readermacOS/iOSMac/mobile testing
pa11yCLI toolNode.jsCI pipeline

12. Common Accessibility Anti-Patterns

Using div or span for interactive elements without adding role, tabindex, and keyboard event handlers is the most common anti-pattern. Div buttons lack keyboard support, screen reader announcements, and native browser behaviors. The fix is simple: use the native button element. Similarly, use native a elements for navigation instead of clickable divs.

Common Mistakes & Fixes

<!-- Anti-pattern: clickable div -->
<div class="btn" onclick="save()">
  Save
</div>
<!-- Fix: use native button -->
<button type="button" onclick="save()">
  Save
</button>

<!-- Anti-pattern: missing label -->
<input type="text" placeholder="Search..." />
<!-- Fix: add associated label -->
<label for="search">Search</label>
<input type="text" id="search"
  placeholder="Search..." />

<!-- Anti-pattern: redundant ARIA -->
<button role="button"
  aria-label="Submit button">
  Submit
</button>
<!-- Fix: remove unnecessary ARIA -->
<button type="submit">Submit</button>

Removing the outline on focus (:focus outline none) without providing a custom focus indicator makes keyboard navigation impossible. Autoplaying media with sound violates WCAG. Using tabindex values greater than 0 creates a confusing tab order. Hiding content with display none when it should be available to screen readers (use visually hidden CSS instead).

ARIA overuse is a significant anti-pattern. Adding aria-label to every element, using redundant roles (role button on a button element), or using aria-hidden true on visible interactive elements all degrade the experience. Remember: no ARIA is better than bad ARIA. Use the accessibility tree to verify your ARIA attributes produce the expected result.

13. Legal Requirements (ADA, Section 508, EAA)

In the United States, the Americans with Disabilities Act (ADA) Title III has been interpreted by courts to apply to websites as places of public accommodation. Section 508 of the Rehabilitation Act requires federal agencies to make electronic and information technology accessible, explicitly referencing WCAG 2.0 Level AA. The Department of Justice finalized rules in April 2024 requiring state and local governments to meet WCAG 2.1 AA.

The European Accessibility Act (EAA), effective June 2025, requires products and services sold in the EU to be accessible, including websites and mobile applications. EN 301 549 is the European harmonized standard that maps to WCAG 2.1 AA. Canada has the Accessible Canada Act, and Australia enforces the Disability Discrimination Act with WCAG 2.0 as the benchmark.

RegulationRegionStandardEffective
ADA Title IIIUnited StatesWCAG 2.1 AAActive
Section 508US FederalWCAG 2.0 AAActive
EAAEuropean UnionWCAG 2.1 AAJune 2025
AODAOntario, CanadaWCAG 2.0 AAActive
DDAAustraliaWCAG 2.0 AAActive

Web accessibility lawsuits have increased dramatically — over 4,000 ADA-related digital accessibility lawsuits were filed in the US in 2023 alone. Proactive accessibility compliance is significantly cheaper than reactive remediation after a lawsuit. Most accessibility regulations converge on WCAG 2.1 Level AA as the minimum standard, making it the practical target for global compliance.

Conclusion

Web accessibility is a continuous practice, not a one-time checklist. Start with semantic HTML, add ARIA only when needed, ensure keyboard and screen reader compatibility, maintain color contrast standards, and test regularly with both automated tools and real users. WCAG 2.2 AA should be your minimum target. Accessible websites are not just legally compliant — they are faster, more usable, and reach a broader audience. Every improvement you make benefits all users, not just those with disabilities.

FAQ

What is the difference between WCAG 2.1 and WCAG 2.2?

WCAG 2.2 adds nine new success criteria to WCAG 2.1, including Focus Not Obscured (AA), Dragging Movements (AA), Target Size Minimum (AA), Consistent Help (A), and Redundant Entry (A). It also removes 4.1.1 Parsing. Sites that meet WCAG 2.2 also meet 2.1 and 2.0.

Is ARIA better than semantic HTML for accessibility?

No. Semantic HTML should always be your first choice. ARIA supplements HTML when native elements are insufficient (custom widgets, live regions). The first rule of ARIA is to not use ARIA if a native HTML element with equivalent behavior exists. ARIA changes semantics but does not add behavior.

What is the minimum color contrast ratio required by WCAG?

WCAG 2.2 Level AA requires 4.5:1 contrast for normal text and 3:1 for large text (18pt+ regular or 14pt+ bold). Level AAA requires 7:1 for normal text and 4.5:1 for large text. Non-text UI components need at least 3:1 contrast.

Do I need to test with a screen reader?

Yes. Automated tools catch only 30-50% of accessibility issues. Manual screen reader testing is essential to verify proper reading order, dynamic content announcements, focus management, and overall user experience. Use VoiceOver on macOS or NVDA on Windows (both free).

Can I use tabindex to control tab order?

Use tabindex 0 to add elements to the natural tab order and tabindex negative one for programmatic focus without tab access. Never use positive tabindex values as they override the DOM order and create confusing navigation. Fix tab order by rearranging DOM elements instead.

How do I make single-page applications accessible?

Manage focus on route changes by moving it to the new content or page heading. Announce route changes with aria-live regions. Ensure browser back button works. Update the document title on each route. Lazy-loaded content should not break tab order or reading flow.

What are the legal consequences of an inaccessible website?

In the US, ADA lawsuits can result in settlements of tens of thousands of dollars plus attorney fees and mandatory remediation. In Europe, the EAA can impose fines from national regulators. Beyond legal risk, inaccessible sites lose an estimated 15-20% of potential customers.

How do I handle accessibility for dynamic content and AJAX updates?

Use aria-live regions to announce dynamic content changes without moving focus. Set aria-live to polite for non-urgent updates (search results updating) and assertive for critical alerts (error messages). Add the aria-live attribute to the container before the content change occurs.

𝕏 Twitterin LinkedIn
Czy to było pomocne?

Bądź na bieżąco

Otrzymuj cotygodniowe porady i nowe narzędzia.

Bez spamu. Zrezygnuj kiedy chcesz.

Try These Related Tools

.*Regex Tester

Related Articles

CSS Architecture Guide: BEM, CSS Modules, CSS-in-JS, Tailwind, Custom Properties, and Dark Mode

Master CSS architecture for large-scale apps. Covers BEM/SMACSS/OOCSS methodologies, CSS Modules in React, styled-components vs emotion vs vanilla-extract, Tailwind utility-first, CSS custom properties for theming, Grid vs Flexbox, container queries, cascade layers, and dark mode.

Kompletny przewodnik po React Hooks: useState, useEffect i Custom Hooks

Opanuj React Hooks z praktycznymi przykladami. useState, useEffect, useContext, useReducer, useMemo, useCallback, custom hooks i React 18+ concurrent hooks.

React Testing Guide: React Testing Library, Jest, Vitest, MSW, Playwright, and Code Coverage

Master React testing from unit to e2e. Covers React Testing Library queries, userEvent, renderHook, jest.mock(), Mock Service Worker (MSW), Vitest, async testing, snapshot tests, Redux/Zustand testing, Playwright vs Cypress, and code coverage with Istanbul.