Accessible UI Patterns

Accessibility isn’t a checklist we tick after we ship. It’s the backbone of usability. When we embrace inclusive patterns, everyone benefits—keyboard users move smoothly, screen reader users receive clear announcements, and sighted users get visible feedback with proper contrast and motion that respects their preferences. This article collects pragmatic patterns you can apply to the components you ship every week.
Semantics first, ARIA second
Start with the HTML that conveys meaning by default. Buttons are button elements, links are a tags with hrefs, and headings are true headings. Many “accessibility fixes” become unnecessary when the right element is chosen in the first place. Use ARIA to fill gaps, not to redesign the platform. If you find yourself adding three roles and five properties, ask whether a simpler semantic approach exists.
Keyboard mechanics: predictable and complete
Every interactive element must be reachable by keyboard in a logical order. That means no custom tabindex gymnastics unless you’re solving a specific trap. The Tab key moves focus forward, Shift+Tab moves backward, arrow keys navigate lists and menus, and Esc dismisses overlays. Consistency is kindness: once users learn the pattern, they can apply it everywhere in your app.
Focus you can see
Remove the outline at your peril. Replace it if you must, but ensure the substitution is visible at a glance, passes contrast ratios, and doesn’t rely on color alone. For complex widgets, manage focus deliberately: send focus into an opened modal, loop focus within it, and return focus to the trigger on close. That single behavior can be the difference between delightful and disorienting.
Announcements, not surprises
When content changes dynamically, tell assistive tech what happened. Use live regions sparingly to announce brief updates such as “Added to cart” or “Filters applied.” For loading states, prefer skeletons to spinners; they are easier to interpret and reduce anxiety. If a long process starts, communicate progress with a determinate indicator where possible.
Color and contrast
Text and interactive elements should meet WCAG AA contrast at minimum. Don’t put essential information solely in color—pair state with an icon, underline links, and provide descriptive text. When you design a palette, test it against real components—inputs with errors, disabled buttons, focus rings on colored backgrounds—because these are the scenarios that fail often.
Accessible component patterns
Here are practical notes for common components:
- Modal: Use dialog semantics (or role="dialog"). Trap focus, label with aria-labelledby, and provide an accessible close button. Prevent background scroll and restore focus to the trigger on close.
- Tabs: Use tablist, tab, and tabpanel roles with keyboard support for arrow navigation. Associate panels via aria-controls, and manage focus to the active tab.
- Accordion: A button controls a region. Toggle aria-expanded and aria-controls. Keep headings real so users can scan the page structure.
- Menu/Combobox: Follow the ARIA practices for listbox/option or menu/menuitem. Handle typeahead, highlight states, and escape behavior predictably.
- Form validation: Associate labels explicitly, describe errors next to fields, and link errors via aria-describedby. Don’t rely on color alone for error states.
Motion that respects users
Animation can help by communicating cause and effect, but it can also harm if it’s excessive. Keep motion subtle, avoid parallax and background scroll hijacking, and respect prefers-reduced-motion by offering minimized animations or none at all. Often, a 150–200ms ease-out transition is all you need to protect context without creating distraction.
Test with tools and humans
Automated tools—linters, color contrast checkers, and browser devtools—catch many issues quickly. Use them in CI. Then test with real users and assistive technologies like NVDA, JAWS, and VoiceOver. Short, frequent tests prevent big surprises later. Keep a small “a11y kit” of scripts and bookmarks that your team can run in seconds during development.
Accessible by default through your system
The easiest way to make accessibility stick is to bake it into your design system. When your components expose the right roles, states, and focus behaviors out of the box, product teams inherit inclusive UX without needing deep ARIA knowledge. That’s leverage. Document patterns, supply code examples, and keep the defaults accessible so customizations don’t accidentally remove critical behavior.
Estimated reading time: 7–8 min.