React - Accessibility Essentials
Overview
Estimated time: 20–30 minutes
Improve keyboard navigation and screen reader support with skip links, ARIA attributes, and live region announcements.
Try it: Skip link, collapsible with ARIA, and aria-live updates
View source
function A11yDemo(){
const mainRef = React.useRef(null);
const [open, setOpen] = React.useState(false);
const [count, setCount] = React.useState(0);
function skipToMain(e){ e.preventDefault(); if (mainRef.current) mainRef.current.focus(); }
return (
<div>
<a href="#main" onClick={skipToMain} style={{position:'absolute', left:-9999}} onFocus={e => e.currentTarget.style.left='8px'} onBlur={e => e.currentTarget.style.left='-9999px'}>Skip to content</a>
<button aria-expanded={open} aria-controls="sect" onClick={() => setOpen(o => !o)}>{open ? 'Hide' : 'Show'} details</button>
<section id="sect" hidden={!open}>
<p>This is a collapsible section. Toggle button updates aria-expanded.</p>
</section>
<main id="main" ref={mainRef} tabIndex={-1} style={{outline:'none', display:'block', marginTop:8}}>
<h3>Main content</h3>
<button onClick={() => setCount(c => c+1)}>Add notification</button>
<div aria-live="polite" style={{marginTop:8}}>{count ? `Notifications: ${count}` : ''}</div>
</main>
</div>
);
}
ReactDOM.createRoot(document.getElementById('try-a11y')).render(<A11yDemo />);
Syntax primer
- Skip link: jump focus to main content; show link on focus.
- ARIA:
aria-expanded
/aria-controls
for toggles;aria-live
for announcements.
Common pitfalls
- Missing keyboard focus styles—ensure focus is visible.
- Toggle content without updating ARIA—keep attributes in sync.
Checks for Understanding
- What does
aria-expanded
indicate on a toggle button? - Why is a skip link useful, and when should it be visible?
Show answers
- Whether the controlled region is expanded (
true
) or collapsed (false
), enabling screen readers to announce state. - It provides keyboard users a quick jump to main content; it should become visible on focus.
Exercises
- Add an
aria-label
to the toggle button and verify screen reader announcement. - Introduce a dismissible alert region using
role="alert"
and test keyboard and screen reader behavior. - Ensure focus is moved to the first heading inside the newly shown section when it expands.