Accessibility isn't a feature — it's a baseline.
Roughly 16% of the global population lives with a disability. When we ship inaccessible software, we're not cutting corners — we're cutting people out. Here's how I approach accessibility as a developer, not a specialist.
I didn't think much about accessibility early in my career. I built interfaces that looked good, worked smoothly with a mouse, and shipped them with a clear conscience. Then I watched a screen reader try to navigate one of my forms. It was like listening to someone read a phone book in a language they didn't speak. That was the moment I realized: I hadn't been building for everyone. I'd been building for people like me.
Accessibility isn't a specialized discipline that only certain developers need to care about. It's a quality bar, the same as performance or security. And like those concerns, it's dramatically easier to build in from the start than to retrofit later.
Start with semantic HTML
Most accessibility issues I encounter in code reviews come from the same root
cause: <div> soup. Developers reach for a generic container
and then bolt on behavior with JavaScript and ARIA attributes, recreating
what the browser already provides for free.
Use <button> for actions, <a> for
navigation. Use <nav>, <main>,
<article>, and <aside> to give your
page structure that assistive technologies can understand. Semantic HTML is
accessible by default — it comes with keyboard handling, focus management,
and screen reader announcements built in.
ARIA is a repair tool for when native semantics aren't enough. It should be your second choice, not your first.
The keyboard test
Here's the simplest accessibility test you can run: put your mouse in a drawer and try to use your application with just a keyboard. Tab through every page. Can you reach every interactive element? Is the focus order logical? Can you see where the focus is?
Most applications fail this test within the first thirty seconds. Custom dropdowns that don't respond to arrow keys. Modals that trap focus — or worse, don't trap focus, letting users tab into invisible content behind the overlay. Single-page applications that move focus nowhere after a route change, leaving screen reader users stranded.
If you can't use it with a keyboard, it's broken. Not "less accessible" — broken. Keyboard navigation isn't a nice-to-have. It's the foundation that every other assistive technology builds on.
Color contrast isn't optional
WCAG AA requires a contrast ratio of 4.5:1 for body text and 3:1 for large text. These aren't arbitrary numbers — they're the threshold at which text becomes reliably readable for people with low vision, color blindness, or simply a screen in direct sunlight.
Test your colors with a contrast checker. Don't convey information with color alone — add icons, patterns, or text labels alongside. That red error border means nothing to someone who can't perceive red. Add an error icon and a text message.
And a common misconception: dark mode isn't automatically accessible. A dark background with light text still needs to meet contrast ratios. Many dark themes fail because designers prioritize aesthetics over readability, using muted grays that look sophisticated but disappear for anyone with impaired vision.
ARIA: use it sparingly, use it correctly
The first rule of ARIA is: don't use ARIA if native HTML works.
A <button> element is always better than a
<div role="button" tabindex="0">. The native element handles
keyboard events, focus, and screen reader announcements without any extra work.
When you do need ARIA, use it precisely. Common patterns that work well:
aria-label for icon-only buttons that have no visible text.
aria-live regions for dynamic content that updates without a page
reload — toast notifications, loading states, real-time counters.
role="alert" for error messages that need immediate attention.
Bad ARIA is worse than no ARIA. When you add role="button" to a
<div> but forget to add keyboard handling, you've lied to
the screen reader. It announces "button" but nothing happens when the user
presses Enter. That's not just inaccessible — it's actively misleading.
Testing accessibility
Accessibility testing works best as a layered approach, from automated to manual:
- Use axe DevTools in your browser. It catches low-hanging fruit — missing alt text, contrast failures, missing form labels. Run it on every page during development.
-
Add
eslint-plugin-jsx-a11yto your linter. Catch accessibility issues at the code level before they reach the browser. It flags missing ARIA attributes, invalid roles, and non-interactive elements with click handlers. - Test with a screen reader monthly. VoiceOver on Mac, NVDA on Windows. Navigate your app the way a blind user would. You'll find issues that no automated tool can catch — confusing announcement order, missing context, interactions that make no sense without visual cues.
Automated tools catch 30-40% of accessibility issues. The rest require human judgment — is the tab order logical? Does this interaction make sense without seeing the screen? Is the error message helpful when you can't see which field it's pointing to? Manual testing catches the issues that matter most.
Accessibility is not a checklist you complete at the end of a project. It's a lens you apply at every decision point — from wireframe to deployment.
Closing thought
The most accessible products I've used weren't built by accessibility experts. They were built by developers who cared enough to test with their keyboard, check their contrast ratios, and use the right HTML elements. They didn't know every WCAG criterion by heart. They just applied a simple principle consistently: can everyone use this?
The bar isn't as high as it seems. Start with semantic HTML. Tab through your app. Check your contrast. Test with a screen reader once a month. These four habits will put you ahead of 90% of the web. And more importantly — they'll make sure the things you build are usable by the people who need them most.