The provided content emphasizes the importance of web accessibility for developers, not only for the benefit of users with disabilities but also for improving code quality, test reliability, and overall user experience.
Abstract
Accessibility, commonly abbreviated as a11y, is a crucial aspect of web development that ensures websites are usable by as many people as possible, including those with disabilities or those using different devices and networks. The article argues that developers should prioritize accessibility because it leads to better code practices, such as using semantic HTML elements, which in turn results in more maintainable and robust tests. It suggests that by adopting accessible development practices, developers can create more resilient applications that are easier to test and refactor, ultimately leading to a better user experience for everyone. The article also points out that accessible development can align with business interests, as it can open up opportunities with organizations that require accessible solutions, and it can future-proof applications against changing requirements and technologies.
Opinions
Accessibility is not just a compliance issue but also provides immediate benefits to developers and users alike.
Writing tests with an accessibility mindset makes them more reflective of real-world usage and less dependent on specific implementations.
Using the correct HTML elements and roles is essential for accessibility and can improve the user experience for all users.
Accessibility considerations can lead to more readable and easier-to-maintain code, reducing technical debt over time.
Developers should not wait for explicit business directives to implement accessibility, as it is a continuous improvement process that should be integrated into daily development work.
The adoption of accessibility practices can make applications more resilient to changes and refactoring, as tests will focus on user-visible effects rather than implementation details.
QA engineers can write more resilient end-to-end tests by using accessible selectors, which are less likely to break with changes in the application's markup.
The article acknowledges that convincing stakeholders to prioritize accessibility can be challenging but emphasizes that early adoption can mitigate future challenges and open up additional business opportunities.
Accessibility: the selfish reasons why developers should care about it
Accessibility (a11y) is not just for others or for later. See how you and your team can benefit from it today!
Accessibility is the practice of making your websites usable by as many people as possible. We traditionally think of this as being about people with disabilities, but the practice of making sites accessible also benefits other groups such as those using mobile devices, or those with slow network connections.
As we’ll see later, we can extend this definition to making your websites accessible to other tools or computer programs too.
What does it mean for me, as a developer?
Essentially, it begins with using the right HTML elements for the job. Use a <progress> element to implement a progress bar, not a <div> in a <div>. Use a <button> to implement a button, not a link or a <div> with an onClick attribute, etc. Or use a UI library that has accessibility built-in, for example: Radix UI, React Aria, or even MUI. Your users will thank you. And so will your future self! But please, for now, read on.
My code works as it is, and my custom markup gives me full control of the UX!
True, sometimes the native HTML elements can be hard to style or customize. When this happens, don’t give up so easily, there’s often a way! Here is an example:
But if you really can’t find a way to use the appropriate elements, and you know what you’re doing, use the markup you like, but try using the right roles.
OK, but how does it help ME exactly?
Well, look at your tests (you have tests rights?). If your app is not accessible or you never cared about accessibility, chances are that your tests are a mess, or very brittle to say the least. You might be targeting elements with test IDs, actual IDs, class names, or even indexes, and dispatching DOM events by hand.
What’s wrong with that?
Your tests might not be a good reflection of reality. Maybe the element you’re clicking is not reachable from the UI. Maybe only a certain area of your <div>-disguised-as-a-button is clickable. The elements you’re targeting may simply not be accessible to all, or you may be missing a bug.
Ummm okay, but I’m just writing a unit test! Don’t I have to run a web browser to use accessibility?
You don’t have to! Your test runner can do it for you, for free. If you change your mindset and consider the test runner as a user with limited abilities, you can start targeting and interacting with your application the way this user would.
Does your component have a button that does something when clicked? Then look for an element with the role “button” and the actual name of the button. Just what a user using assistive technology would do. Why would you need a test ID for this?
This isn’t the worst I’ve seen! But there are a few issues with this code:
An impaired user would not be able to recognize that there is a button and a progress bar displayed on the screen, as they lack accessible roles
Keyboard usage will be limited (you can’t put the focus on the button for instance)
The tests rely on implementation details: your “button” needs to be implemented with a specific test ID, the “progress bar” must have an inner element with a specific test ID and its styles should be directly correlated with its width.
So now let’s use the right HTML elements and target them the way the user would, without changing the functionality or degrading the user experience (quite the opposite in fact: we’re upgrading the UX!):
The <div>s are now proper <button> and <progress> elements, which are accessible by default.
We can then target the relevant elements in the tests with screen.getByRole(“button”) and screen.getByRole(“progress”) , and we can assert that the value of the progress bar is 10 with expect(progressbar).toHaveValue(10) . We no longer rely on how the button and progress bar are implemented.
Oh and userEvent.click(button) will now ensure that if the click works in our test, it also works in real life.
I think these tests are too “high level” to be called unit tests...
(Sigh) You’re just giving me more work and more things to think of…
I was hoping you’d find your code and tests more readable and easier to maintain as a result. But fine.
You may not have noticed it, but by using accessibility, your tests, and by extension your app, are getting more resilient. When your tests interact with your components from the user’s perspective, and when they focus on the visible effects (how the UI changes as a result of interacting with it), rather than on what code executes, it no longer matters how your components are implemented.
You can rewrite your button, list, or dropdown. You can change your libraries. You can change your styles or your class names. Your tests will not change.
How many times did you have to throw away your tests or rewrite them as you were editing some components? Isn’t the point of a test to know if it still passes after you refactor your code? Failing tests shouldn’t be the result of the test itself being broken (probably because it depended on the old implementation or it was testing the implementation rather than the visible effects). Tests should fail because the behaviour of the component has changed.
Assuming accessibility can help me… I have QA engineers in my team writing E2E tests. They rely on my current markup. Their tests will break if I change that markup.
Yeah, that’s essentially the same point as earlier. Their tests are probably brittle.
You could agree with QA to use certain attributes on the components they rely on (like data-testid), but it wouldn’t make their tests more resilient in the first place. By using accessible selectors, like in our tests, it no longer matters if we change the implementation of the component or move it down or up in the hierarchy.
But the point is: if we, developers, QA engineers, end users, and tools start to speak the same language (the accessibility language), we will do ourselves a favour by improving the way we work, and we’ll make our apps more resilient and inclusive.
The thing is: we’re on a tight schedule, and the business will never allocate time or money for this.
If you’ve been in the industry for long enough, you already know that you cannot wait for the business’ approval to tackle your tech debt. This is a daily effort. When a component starts to smell, try to improve it the next time you work on it, even if only marginally. Get to know its boundaries, its limits, and its quirks. Write tests for its use cases. Soon the refactoring that’s needed will become more evident.
Well, that’s the same thing for accessibility. When you write your next test case, try to write it in an accessible way. If you can’t do it (for example you have to resort to test IDs), you might have identified an accessibility issue, which will guide your next refactoring. Consider replacing an HTML element with a more appropriate one, or consider adding the right roles and accessible properties. This can be done one step at a time.
Your sales department will thank you when they sign a juicy contract with a company or public organization that requires a certain level of accessibility (kidding, they’ll never thank you).
I’m still not convinced. I just don’t see the need or the urge for it. It’s simply not worth the effort.
Alright, thank you for reading up here then 😅 I hope that maybe I planted a seed and that someday this seed will grow and help you in your task.
Maybe you’ve already found your balance and accessibility is just not part of the equation. If that’s the case, please leave a comment, because I’m always curious to know what works for others.
Well actually, I like the idea and I would like to know more about it! Where do I start?
Glad to hear that!
Remember, this article is only just scratching the surface. There will be other considerations to make before your app is truly accessible to all. Getting started is probably the hardest part. But the earlier you do it, the less painful it is!
Be reassured that the first accessibility level starts low. For example, level A requires alternative texts for non-text contents, using the right elements for the job (semantic markup) and keyboard navigation (do not rely solely on the mouse). Healthy practices will allow you to reach that level for free.
The second level (AA), which most organizations strive to meet, adds extra requirements, such as minimum contrast levels, proper roles, headings and labels, etc… The techniques I mentioned here will set you on the right track.