What we learned by running an accessibility audit of our app
We recently underwent an accessibility audit (thanks to Access42) for our app due to compliance regulations for large companies in France. Initially, we believed we were in good shape because we use modern tools, adhere to basic HTML structures, and avoid unusual ergonomics. However, we decided to invest effort into this area as we needed to meet a minimum score, and the scoring system is quite stringent: any failure on a specific criterion on any audited page counts as a failure, which can quickly degrade the overall score. That's when we realized just how poor our accessibility was, how complex the subject is, and how much work lay ahead of us... Before diving in As a typical developer, I initially believed that accessibility was merely a technical issue to be resolved. However, I soon realized I was mistaken, and I would like to share our experience before delving into more concrete details. Get a proper training It's easy to assume that accessibility is straightforward, but like everything in web development, there's a rich history, numerous quirks, and backward compatibility issues that complicate matters. Fortunately, four developers and I had the opportunity to participate in a three-day training session, including hands-on testing of our own app. This was incredibly instructive. We were able to experiment with tools and ask questions on the spot, which was far more efficient than spending hours on Stack Overflow trying to figure out why VoiceOver wasn't behaving as expected... Involve every stakeholder A web app should be designed with accessibility in mind from the outset, much like performance and other cross-cutting concerns. While developers can implement fixes, these solutions are often less effective for users and require more effort from the team. Examples include manually adding aria-label attributes to icon-only buttons, creating textual alternatives for complex objects, and managing focus states manually when informations are spread on the interface. Certain design-specific aspects, such as text size, color contrasts, and considerations for color blindness, cannot be addressed by developers alone. Currently, here, developers are primarily responsible for ensuring the accessibility of the product through testing. However, we hope that a culture of accessibility will gradually permeate all aspects of our work over time. Understanding the accessibility tree You might already be familiar with the DOM (Document Object Model) and CSSOM (Cascading Style Sheets Object Model), but we discovered that there is another, less visible underlying model: the accessibility tree. It is primarily derived from HTML elements and results in four properties for each element: name: a kind of identifier description: a secondary string describing the element, similar to a tooltip role: one of the list of roles. By default, it is generic; a button will be button, an a will be link, and it can be overridden by the role="" attribute. state: indicates if the element is currently active, expanded, pressed, checked, etc. Understanding these properties is crucial for correctly using attributes like aria-label, title, aria-describedby, and so on, as well as knowing their priority. For example, aria-labelledby takes precedence over aria-label. Modern browsers now offer a view of the accessibility tree in their developer tools, making it easier to debug. More on this later. Subjectivity One final note before diving in, regarding what may be the most challenging aspect of accessibility: subjectivity. Here are some scenarios where it can be difficult because no tool can help you make a decision: Should this text be a heading or a paragraph? An image has an alt attribute, but is it truly meaningful? A "skip" button has been added, but is it genuinely useful?? Should this notification be polite or assertive? In short, even a 100% accessible website could be frustrating to use with a screen reader. The best way to assess this is to use it ourselves under "real" conditions. The only downside is that it's time-consuming, so I suspect few companies actually do it. Using accessible librairies Chances are that you rely on a UI library for common components. You first want to make sure it's already accessible enough, or else you'll lose a huge amount of time trying to fix errors that you don't actually control. In our case, we're migrating from ElementPlus to Radix Vue mainly for this reason. It seems modern tools finally treat accessibility as a first class citizen, but it was not the case just a few years ago! Ark UI looks like a good alternative too. You can check their docs and even use the tool below to check its accessibility compliance. We can also refer to Offical WCAG rules for simple and framework-agnostic examples. Manual testing Now that we have the basic theory, it's time to get our hands dirty and find issues and test

We recently underwent an accessibility audit (thanks to Access42) for our app due to compliance regulations for large companies in France. Initially, we believed we were in good shape because we use modern tools, adhere to basic HTML structures, and avoid unusual ergonomics.
However, we decided to invest effort into this area as we needed to meet a minimum score, and the scoring system is quite stringent: any failure on a specific criterion on any audited page counts as a failure, which can quickly degrade the overall score.
That's when we realized just how poor our accessibility was, how complex the subject is, and how much work lay ahead of us...
Before diving in
As a typical developer, I initially believed that accessibility was merely a technical issue to be resolved. However, I soon realized I was mistaken, and I would like to share our experience before delving into more concrete details.
Get a proper training
It's easy to assume that accessibility is straightforward, but like everything in web development, there's a rich history, numerous quirks, and backward compatibility issues that complicate matters.
Fortunately, four developers and I had the opportunity to participate in a three-day training session, including hands-on testing of our own app. This was incredibly instructive. We were able to experiment with tools and ask questions on the spot, which was far more efficient than spending hours on Stack Overflow trying to figure out why VoiceOver wasn't behaving as expected...
Involve every stakeholder
A web app should be designed with accessibility in mind from the outset, much like performance and other cross-cutting concerns. While developers can implement fixes, these solutions are often less effective for users and require more effort from the team. Examples include manually adding aria-label attributes to icon-only buttons, creating textual alternatives for complex objects, and managing focus states manually when informations are spread on the interface.
Certain design-specific aspects, such as text size, color contrasts, and considerations for color blindness, cannot be addressed by developers alone. Currently, here, developers are primarily responsible for ensuring the accessibility of the product through testing. However, we hope that a culture of accessibility will gradually permeate all aspects of our work over time.
Understanding the accessibility tree
You might already be familiar with the DOM (Document Object Model) and CSSOM (Cascading Style Sheets Object Model), but we discovered that there is another, less visible underlying model: the accessibility tree.
It is primarily derived from HTML elements and results in four properties for each element:
-
name
: a kind of identifier -
description
: a secondary string describing the element, similar to a tooltip -
role
: one of the list of roles. By default, it isgeneric
; abutton
will bebutton
, ana
will belink
, and it can be overridden by therole=""
attribute. -
state
: indicates if the element is currently active, expanded, pressed, checked, etc.
Understanding these properties is crucial for correctly using attributes like aria-label
, title
, aria-describedby
, and so on, as well as knowing their priority. For example, aria-labelledby
takes precedence over aria-label
. Modern browsers now offer a view of the accessibility tree in their developer tools, making it easier to debug. More on this later.
Subjectivity
One final note before diving in, regarding what may be the most challenging aspect of accessibility: subjectivity.
Here are some scenarios where it can be difficult because no tool can help you make a decision:
- Should this text be a heading or a paragraph?
- An image has an
alt
attribute, but is it truly meaningful? - A "skip" button has been added, but is it genuinely useful??
- Should this notification be polite or assertive?
In short, even a 100% accessible website could be frustrating to use with a screen reader. The best way to assess this is to use it ourselves under "real" conditions. The only downside is that it's time-consuming, so I suspect few companies actually do it.
Using accessible librairies
Chances are that you rely on a UI library for common components. You first want to make sure it's already accessible enough, or else you'll lose a huge amount of time trying to fix errors that you don't actually control. In our case, we're migrating from ElementPlus to Radix Vue mainly for this reason.
It seems modern tools finally treat accessibility as a first class citizen, but it was not the case just a few years ago! Ark UI looks like a good alternative too. You can check their docs and even use the tool below to check its accessibility compliance.
We can also refer to Offical WCAG rules for simple and framework-agnostic examples.
Manual testing
Now that we have the basic theory, it's time to get our hands dirty and find issues and test fixes. Here are the main tools we used:
Browser accessibility devtools
Browsers have come a long way in terms of tooling, and it's really helpful to understand the state of a specific element and why it's considered that way. For instance, the aria-label
attribute takes precedence over the title
attribute, so Chrome indicates that it will be ignored:
It's not as clear in Firefox, but other information is provided:
Each browser offers different tools with their own advantages and disadvantages, so feel free to try them out to find your preferences.
Axe browser extension
Axe is probably the most well-known suite of tools for testing and improving accessibility. It is essentially included in every major testing solution, as we'll see next.
You can find the Axe extensions for browsers on their website (available for Chrome, Firefox, and Edge). It offers a lot of tools to identify accessibility issues:
While it might not be the most feature-complete, as indicated in this study by the British Government, it is probably better to have consistent test results across your tools (unit tests, manual tests, E2E tests, etc.) than ultra-exhaustive error reports.
Windows, Firefox & NVDA
This setup is the most widely used worldwide, and NVDA is the most valid and feature-complete free tool available, so it should be preferred when doing tests. If you're on Mac, you can use a virtual machine (we chose Parallels Desktop with Windows 11, which took about 30 minutes to set up and ~130€ one time payment).
MacOS, Safari & VoiceOver
VoiceOver is included in every Mac and can be toggled by pressing CMD+F5. It's pretty good by default, but it is known to have some quirks. For instance, it won't read aloud any alert that uses anything other than alert
(log
or status
won't work). If you're on Windows, unfortunately, there's no way to emulate it locally.
Using BrowserStack
Online virtual machines can be useful too. We didn't try them, but BrowserStack currently supports screen readers, and there could be other tools offering similar functionality.
Automated Testing
Unit Tests
We believe unit tests are not particularly useful for accessibility, as checking only for HTML attributes is generally insufficient. Tools like Axe can handle this better than manual unit tests, so we didn't use them at all.
End-to-End Accessibility Tests with Cypress
End-to-end tests are better suited for accessibility checks because they closely mimic what users will see and interact with. However, there are some quirks with Cypress, such as handling tab keys to check for focus. You might want to look into cypress-real-events for a potential solution. (Edit: It seems like this issue is finally being considered in Cypress priorities).
I suppose Playwright might not suffer from those issues as it uses a different, more native way of controlling the browser, but we don't use this tool directly for now.
Axe Plugin
We used the cypress-axe plugin to easily integrate Axe into our tests. The upside is that it's straightforward to use; the downside is that reading errors can be challenging (clicking on lines provides better feedback, though):
Cypress Cloud accessibility add-on
Luckily for us, Cypress released a full featured accessibility add-on not so long ago.
It relies on Axe too, but it's much more integrated in the ecosystem. For instance, the online report is very nice (I can't expose the visual of our app unfortunately):
Also, the Slack integration is quite nice too:
The obvious downside is that it's a paid add-on, and it's quite expensive