Web accessibility ensures that websites work for all users — including those using screen readers, keyboard-only navigation, or other assistive technology. Firefox has a dedicated Accessibility panel in DevTools that surfaces accessibility issues. This guide covers what to check and how Firefox's Accessibility Inspector helps.
Firefox Accessibility Panel
Open DevTools (F12) → Accessibility tab.
The panel shows:
- An accessibility tree — the hierarchy of accessible elements (what screen readers see, not the DOM)
- Properties for each element: role, name, description, states, actions
- Checks section: run automated accessibility audits
To find issues:
- Click "Check for Issues" (dropdown next to the play button)
- Select: All Issues, Keyboard, Text Labels, or Contrast
- Issues appear highlighted on the page and listed in the panel
ARIA Roles and the Accessibility Tree
Every HTML element has an implicit ARIA role. DevTools shows you the computed role:
<!-- Implicit roles -->
<button>Click</button> <!-- role: button -->
<nav>...</nav> <!-- role: navigation -->
<h1>Title</h1> <!-- role: heading, level: 1 -->
<input type="text"> <!-- role: textbox -->
<ul><li>Item</li></ul> <!-- role: list + listitem -->
<!-- Override with explicit role -->
<div role="button" tabindex="0">Custom Button</div>
In the Firefox Accessibility panel, click any element to see its computed role and accessible name.
Accessible Names
Every interactive element needs an accessible name — what screen readers announce:
<!-- ✅ Button with text content -->
<button>Save document</button>
<!-- ✅ Icon button with aria-label -->
<button aria-label="Save document">
<svg aria-hidden="true">...</svg>
</button>
<!-- ✅ Input with associated label -->
<label for="email">Email address</label>
<input type="email" id="email">
<!-- ✅ Input with aria-labelledby -->
<h2 id="section-title">Contact Info</h2>
<input aria-labelledby="section-title" type="text">
<!-- ❌ Icon button without label — screen reader says nothing useful -->
<button>
<svg>...</svg>
</button>
Firefox Accessibility panel shows "Name: " as empty when the accessible name is missing.
Keyboard Navigation
All interactive elements must be reachable by keyboard:
<!-- These are naturally focusable -->
<a href="...">Link</a>
<button>Button</button>
<input type="text">
<select><option>...</option></select>
<textarea></textarea>
<!-- Custom interactive elements need tabindex -->
<div role="button" tabindex="0" onclick="...">Custom button</div>
<!-- Remove from tab order when hidden -->
<div hidden tabindex="-1">Not reachable by tab</div>
<!-- Manage focus manually for modals/dialogs -->
<dialog id="modal">
<button autofocus>First focus</button>
<!-- Focus is trapped inside modal -->
</dialog>
Test keyboard navigation:
-
Tabthrough the page — can you reach every interactive element? -
Shift+Tabto go backward -
Enter/Spaceto activate buttons and links -
Escapeto dismiss modals/menus - Arrow keys for radio groups, dropdowns, and custom widgets
Color Contrast
Firefox's Accessibility panel checks color contrast automatically.
The WCAG requirements:
- Normal text (< 18px or < 14px bold): 4.5:1 ratio minimum
- Large text (≥ 18px or ≥ 14px bold): 3:1 ratio minimum
- UI components (icons, input borders): 3:1 minimum
/* ❌ Fails contrast: light gray on white */
.muted { color: #9CA3AF; background: #ffffff; } /* 2.85:1 */
/* ✅ Passes: darker gray */
.muted { color: #6B7280; background: #ffffff; } /* 4.63:1 */
Firefox DevTools color picker shows contrast ratio when you click a color value in the Styles panel.
Semantic HTML
Semantic HTML gives screen readers structure for free:
<!-- ❌ Non-semantic -->
<div class="page-header">
<div class="logo">...</div>
<div class="navigation">
<div class="nav-item"><a href="/">Home</a></div>
</div>
</div>
<!-- ✅ Semantic — screen readers understand the structure -->
<header>
<a class="logo" href="/">...</a>
<nav>
<ul>
<li><a href="/">Home</a></li>
</ul>
</nav>
</header>
Screen reader users can navigate by landmarks (header, main, nav, footer, aside) to jump directly to sections.
Live Regions
For dynamic content updates, use ARIA live regions:
<!-- Announce changes to screen readers -->
<div role="status" aria-live="polite">
<!-- Status messages (save confirmation, validation feedback) -->
</div>
<div role="alert" aria-live="assertive">
<!-- Critical alerts (error messages) -->
</div>
<!-- Updating a live region: screen reader announces the change -->
document.querySelector('[role="status"]').textContent = 'Form saved successfully.';
polite — reads after current content. assertive — interrupts immediately (use for errors only).
Focus Management for SPAs
Single-page apps navigate without page reloads — screen readers don't get the "new page" signal:
// When navigating to a new route
router.on('navigate', (route) => {
// Update document title
document.title = route.title;
// Move focus to the main content or page title
const heading = document.querySelector('h1');
if (heading) {
heading.setAttribute('tabindex', '-1');
heading.focus();
// Remove tabindex after focus (so it doesn't stay focusable by tab)
heading.addEventListener('blur', () => heading.removeAttribute('tabindex'), { once: true });
}
// Announce the navigation
const announcer = document.getElementById('route-announcer');
if (announcer) announcer.textContent = `Navigated to ${route.title}`;
});
Testing with Firefox
Beyond DevTools:
- Firefox with NVDA (Windows): NVDA is a free screen reader — test your site with it
- Tab through your site with JavaScript disabled to verify logical tab order
- Zoom to 200% — does content still work and not overflow?
- High contrast mode — Windows High Contrast, macOS Increase Contrast
The Firefox Accessibility Inspector's automated checks catch common issues, but manual testing with a screen reader catches the real user experience.
Top comments (0)