JavaScript frameworks continue to rise in popularity. For example, according to the 2024 WebAIM Million report, more than seventy thousand of the top million home pages use React. Other common frameworks like Vue are used on over forty thousand home pages. In total, JavaScript frameworks were detected on 30 percent of the top million home pages.
For the past few years, the vast majority of websites that I’ve personally audited have used one of these frameworks. And while I can’t definitively say whether these frameworks are the root cause of the barriers that I’ve found, I can say that they’ve created their own challenges.
What to expect from an audit
When a company is trying to figure out whether its website is accessible, their first step is typically to conduct an audit or hire someone to do so. From there, auditors test the website in browsers as if they’re real customers, running the same assistive technologies that people with disabilities use. What they’re testing is all just HTML and CSS. Here’s an example to illustrate what I mean.
Let’s say that I’m auditing a website and I come across an image button.
After checking with the browser’s developer tools, I might find that the markup for this button looks something like this:
<button><img src="./images/pencil.png"></button>
That button has no content besides an image. And because the image has no text alternative, the button has no label. People navigating to the button with a screen reader won’t be able to tell what it’s for. So I would end up reporting this as a failure of at least two WCAG success criteria:
- 1.1.1 Non-text Content – the image has no
alt
attribute - 4.1.2 Name, Role, Value – the
<button>
has no label
My recommendation would be something like this:
For
<img>
elements that contribute to the label of a button, apply analt
attribute with a value that briefly describes the button’s action.
The goal here would be that the corrected markup would look something like this:
<button><img src="./images/pencil.png" alt="Edit billing address"></button>
That’s not the only way to address this issue. But it is the approach that may be the simplest to implement and uses attributes that are standard for the HTML elements already being used. Because I’m interacting with the content that’s rendered in the browser, the advice that I give references these HTML elements and attributes.
What a developer sees
Let’s say you work at a company whose website is being audited. What comes after the results of that audit are in? Well, if you’ve just received those results, typically you’ll want to start fixing the things that were found and prioritize critical barriers for your users. So now you take that advice from the auditor about how to fix the markup. You dig into your React code and see this:
<SomeLibraryIconButton>
<IconPencil/>
</SomeLibraryIconButton>
Here’s where things can start to fall apart. Because there’s a framework layered between the developer and the HTML that’s being produced, all the markup that was reported in the audit no longer matches up. They’re looking at a component, not the actual HTML elements. So all that information from the audit about what attributes to add to the markup sounds irrelevant (even though it’s valid advice).
What’s the remediation gap?
The idea of a remediation gap comes from a talk that I gave about single page application accessibility at the 2024 CSUN Assistive Technology conference. It describes the breakdown in communication and knowledge that’s rising from an overreliance on JavaScript frameworks to build web content. It can leave developers confused, consultants struggling to help, and people with disabilities still having to deal with inaccessible websites daily.
You can think of the remediation gap as the culmination of these parts:
- There’s a disconnect between the code that developers write and the resulting markup that’s generated.
- Consultants’ accessibility advice is in terms of HTML, CSS, and commonly understood interaction patterns.
- Developers have difficulty translating that advice into their specific framework.
Loss of knowledge
By design, JavaScript frameworks abstract markup into reusable blocks of code called components. This lets developers save time and effort by creating a common source in their code for every instance of a particular user interface.
<div class="MuiFormControl-root MuiTextField-root css-i44wyl">
<label class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl
MuiInputLabel-animated MuiInputLabel-sizeMedium MuiInputLabel-outlined
MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl
MuiInputLabel-animated MuiInputLabel-sizeMedium MuiInputLabel-outlined
css-6yqonq" data-shrink="false" for="outlined-basic"
id="outlined-basic-label">Outlined</label>
<div class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary
MuiInputBase-formControl css-1xrtwuv">
<input aria-invalid="false" id="outlined-basic" type="text"
class="MuiInputBase-input MuiOutlinedInput-input css-h4os0j" value="">
<fieldset aria-hidden="true" class="MuiOutlinedInput-notchedOutline css-nqlg3w">
<legend class="css-yjsfm1"><span>Outlined</span></legend>
</fieldset>
</div>
</div>
This block of almost nine hundred characters is what gets output by Material UI’s text input component. Having to manually write this markup for each field in a form could be really cumbersome and difficult to maintain over time. If you were using this component and if you had needed to change a class name or adjust the element nesting, that would mean replicating that change everywhere that you had a text input. Instead, these frameworks let you condense this markup into a much smaller code footprint:
<TextField id="outlined-basic" label="Outlined" variant="outlined"/>
This is the React code that you’d write for the same exact markup. It’s only sixty-eight characters and it comes with the benefit that if Material UI ever had to change the output markup, that could be done in one place and applied automatically to each instance where the component were used. This is undoubtedly beneficial for code development, and I’m in no way trying to discourage using these frameworks. But I am trying to raise awareness of the implications that come with this approach.
What are the effects of component-based architectures? They mean that developers no longer have to know HTML to write HTML. When it comes to accessibility, this is not a good thing. The vast majority of accessibility lives in the markup. Not understanding which elements to use or what is even valid to do in the language is always going to cause accessibility barriers.
I wish I were overstating the degree to which this has become an issue. But when I regularly talk to “full-stack developers” who don’t know how to write an unordered list or who don’t know that you can’t nest a button inside of a link, I’m convinced that the term “full-stack” has always been meaningless.
Consulting in a JavaScript world
There are a wide variety of clients out there. Some are dedicated to accessibility and they want to do right by their customers. Others are just looking to get past a lawsuit and move on to the next thing. But at the end of the day, consultants get roughly the same level of information from any client when we’re asked to perform an audit:
- What do you need us to test?
- How can we access that?
- Do we need any credentials or other instructions to access this?
I’ve never heard of clients sharing information about their source code when asking for an accessibility audit. That’s not to say it doesn’t happen, but I’d wager that it’s not common. If consultants had this information, it’s possible that they could include targeted advice for the frameworks or component libraries that you’re using. Though to be realistic, there are hundreds of frameworks out there with third-party component libraries for each. The likely outcome is that consultants would only be able to cater to a few.
Call to action
If unaddressed, the remediation gap will only get worse. The digital industry will continue to create more and more ways to make the development process faster. And be it JavaScript frameworks, generative AI, or something else that we don’t have a word for yet, it’s only going to pull developers further from their understanding of semantics. The challenge of making a more accessible web will become harder and harder to achieve. But there are things that can be done on both sides to get ahead of this.
Developers’ actions
Educating yourself
First things first. If you’re a developer who’s working on the front end of a website, please learn the basics of HTML. And if you might not be familiar with HTML, I’d recommend that you start that journey by checking out some of these resources:
- Introduction to HTML by Mozilla
- Practical Accessibility by Sara Soueidan
- HTML Tutorial for Beginners by EJ Media
- Rote Learning HTML & CSS by Jens Oliver Meiert
If you can understand how elements are structured and what semantics they provide, you’ll be off to a good start with accessibility. And if you can, try to learn what the language does and doesn’t allow.
For example, when creating an unordered list this is allowed:
<ul>
<li>Wicked</li>
<li>Hadestown</li>
<li>Hamilton</li>
</ul>
This isn’t allowed because only list items can be direct children of an unordered list:
<ul>
<div>
<li>Wicked</li>
<li>Hadestown</li>
<li>Hamilton</li>
</div>
</ul>
And this most certainly isn’t useful:
<div aria-label="List">
<div aria-label="List item">Wicked</div>
<div aria-label="List item">Hadestown</div>
<div aria-label="List item">Hamilton</div>
</div>
And before you ask, yes, I have encountered both of those incorrect examples in the real world.
Interpreting advice
Don’t stop at dropping in a component’s tag and calling it a day. Every prop
that you add and every component that you nest can affect your application’s accessibility. Once you understand what your components are actually outputting, that can help you better understand the advice that you might get from accessibility consultants. So—for instance—if you might be looking at a bug about missing alt
text, you’ll have a better idea about which prop that might correspond to in your source code.
<SomeLibraryIconButton aria-label="Edit billing address">
<IconPencil/>
</SomeLibraryIconButton>
Checking documentation
Great developers document their code. Amazing developers read and understand the documentation written by others.
Someone smart, probably
If you’re building a new webpage, odds are that you’re not starting from scratch—you’ll probably be making use of an external library that already comes with the basic website building blocks like buttons and form fields. Make sure that you review each library’s documentation before you commit to using it:
- Check to see whether the library has even considered accessibility.
- Check for component-level documentation on using them accessibly.
If the library that you want to use doesn’t say anything about accessibility, you should probably reconsider using it in the first place. I’ve seen countless times where a developer is trying to fix something that I had reported, and they hit a brick wall because their problem is actually rooted in some external code that they’re importing.
Make sure that you’re checking the components’ documentation for any accessibility properties that you need to account for. Libraries may claim that their components are accessible, but the catch is that they’re only accessible if developers use them as the components’ authors had intended. For example, their component may have a prop
for defining alt
text, and that alt
text may even come with a default value. But considering the variety of possible alternative texts, how likely do you think it is for that default value to be suitable for your use case?
Consultants’ actions
Accessibility consultants can help too. While there’s certainly a lot of responsibility on developers who use these frameworks, consultants can also play a role in making developers’ lives easier.
Giving technology-specific advice
If you as a consultant can learn what types of frameworks or component libraries developers are using, then you may be able to adjust your advice so that it’s easier for developers to translate into code.
This is unquestionably a ton of effort. But I think it can be worth it if some consultants who can take on the cognitive load to do so might be open to learning some of the more technical aspects of these frameworks and incorporating them into their advice—because not all of their customers write plain HTML. Ideally, they might also store that advice in their internal knowledge bases so that they can reuse it for the next time they come across a client who uses that same framework. That way, every improvement that they make to their advice can have compounding benefits.
Offering multiple solutions
There is usually more than one solution to any given accessibility problem. So if consultants only give one solution in their advice, and if that solution doesn’t align with what developers’ frameworks let them do, that can make it more difficult for the developers to implement that advice.
Let’s amend my previous recommendation for an image button as an example:
For buttons whose content only contains an image, provide a text alternative that briefly describes the button’s action. You can define that text alternative in any of these ways:
- You can apply an
alt
attribute directly on the<img>
element inside the button- You can apply an
aria-label
attribute directly on the<button>
element that contains the image- You can add visually-hidden text inside the
<button>
element and then hide the<img>
element from screen readers by using either an emptyalt
attribute oraria-hidden="true"
All three techniques are equally accessible. But by providing multiple options the developer can pick the one that’s more easily supported by their components.
Ideally, each of these techniques would also come with markup examples so that developers can compare them to what their components return.
Summary
JavaScript frameworks like React can be great for scaling front-end code. And I don’t want to discourage using them. But they’re also creating a separation between developers and their familiarity with markup. And since accessibility lives in the markup, this can increase the chances that websites that are built with these frameworks might run into accessibility issues and that it might be harder to fix those issues.
Please, please, please, do not rely on these frameworks until you understand the basics of HTML and CSS. Because at the end of the day, there’s only so much that accessibility consultants can do to help if developers lose sight of the “front-end” in “front-end development.”
Image credit: Mind the Gap photo by AXP Photography
Comments
Many, many thanks for this article. I am both a screen reader user and a sometimes accessibility reviewer of websites. Wearing either hat, I have grumbled for some time to anyone who can’t escape about the negative impact of frameworks. My quote for the year is: “Now I am become Javascript frameworks, the destroyer of semantics”. As a reviewer I did find your even-handed approach to the issues helpful. As a consumer though, repeatedly being confronted with rubbish sites (in terms of coding) does get very tedious. One site I visit often , for example, because of the content applies the title of the article as alt text to each image on the page and that’s a minor issue. And don’t get me started on forms – so easy to code accessibly for anyone who knows semantic code but so few I encounter provide a straight forward experience.
Some how frameworks need to be more heavily scrutinised for the quality of their output and people who use them need to understand semantic code. I will cease ranting at this point.