Accessibility Isn't Optional
After building an inaccessible feature and watching a screen reader user fail to use it, accessibility stopped being a checkbox and became a requirement.
#Accessibility #a11y #Frontend
The Wake-Up Call
The wake-up call was watching a screen reader user try to navigate a feature I'd built. I'd built a custom dropdown component — styled to match the design, with smooth animations and keyboard navigation that I'd tested myself. It worked perfectly with a mouse and with tab-based keyboard navigation, and I'd considered it done. Watching a screen reader user encounter it was a different experience entirely. The screen reader announced the dropdown as a generic element with no label, couldn't communicate the selected state, and got stuck in a loop when the dropdown was open. The user gave up after thirty seconds and asked someone for help. That was the moment accessibility stopped being a theoretical concern and became a concrete responsibility.
The thing that made it worse was that the fix wasn't hard. The component needed proper ARIA attributes (role, aria-expanded, aria-selected, aria-label), keyboard handlers that followed the ARIA design pattern for comboboxes, and focus management that moved focus into the dropdown when it opened and restored it when it closed. None of those changes took more than a few hours to implement, but I hadn't implemented them because I hadn't known they were necessary. The gap wasn't effort — it was knowledge, and the knowledge gap meant my "done" feature was unusable for a meaningful subset of users.
Building Accessible from Day One
After that experience, I made accessibility a first-class requirement in every component I built, and the difference in approach is significant. Building accessible from day one means starting with semantics — using the right HTML element for the job (button for buttons, nav for navigation, main for main content) rather than div with click handlers — and layering ARIA attributes on top only when the semantic HTML doesn't cover the use case. Semantic HTML gives you accessibility for free: a button is keyboard-accessible, announced correctly by screen readers, and focusable by default. A div with an onClick gives you none of that, and you have to add it manually with ARIA attributes and JavaScript.
The second principle is keyboard-first design. If a feature works with a keyboard, it works for screen reader users, keyboard-only users, and users of assistive technologies that emulate keyboard input. Testing with a keyboard — tabbing through the interface, using Enter and Space to activate, using Escape to close — catches the majority of accessibility issues that automated tools miss. We added keyboard testing to our definition of done, and the result was components that worked better for everyone, not just for assistive technology users. Keyboard navigation is faster than mouse navigation for power users, and the focus management that screen reader users depend on also helps users who tab through forms quickly.
The Broader Lesson
The broader lesson is that "done" is a claim about who can use the feature, and if you haven't tested with assistive technology, you don't actually know who can use it. Accessibility testing — running a screen reader, navigating with a keyboard, using automated tools like axe-core — is a skill that takes practice to develop, and it's a skill that every frontend developer should have. The cost of building accessible from the start is small; the cost of retrofitting accessibility onto an inaccessible codebase is large; and the cost of leaving a feature inaccessible is borne entirely by the users who can't use it, which is a cost they didn't choose to pay.
Accessibility is also, counterintuitively, a quality marker for the entire codebase. Teams that take accessibility seriously tend to take other quality dimensions seriously — performance, testing, documentation — because the mindset that says "this needs to work for all users" is the same mindset that says "this needs to work in all conditions." Teams that treat accessibility as an afterthought tend to treat other quality dimensions as afterthoughts too. I've started using accessibility as a signal when evaluating codebases: if the components are accessible, the rest of the code is probably well-built; if they're not, there are likely other quality issues lurking.