In this day and age of web development being done using mostly JavaScript frameworks, semantic HTML has been left behind. In its place we see more developers using ARIA (Accessible Rich Internet Applications) to fill in the gaps and make their content accessible.
However, a scary trend that has been seen lately is that development teams have solely relied on ARIA for making content accessible. What is left is a giant mess of ARIA that is either incorrect, difficult to understand, or leaves developers wondering what they have to do to make it accessible again.
In order to understand the tangled web of ARIA that is being seen in web development, we must first understand the first rule of ARIA.
First Rule Of ARIA
In the accessibility community there is a saying about ARIA. "The first rule of ARIA is don't use ARIA". Although blunt, and most times misunderstood, there is a lot of truth to this. But what does this truly mean?
If there is a semantic HTML tag to use then you should first and foremost use that. Semantic HTML tags have all the built in accessibility you need, without any of the work of ARIA. It is clean, simple, and easy to use a semantic HTML tag versus having to add a lot of ARIA attributes to HTML tags such as <div>
and <span>
.
But even with the battle cry of the first rule of ARIA, development teams continue to ignore the plea, and end up with a giant mess of ARIA based components. But how do they get to that point? Let's take a look by going through a web development scenario!
ARIA First Development Approach
Let's say there is a development team that develops in React. The developers on the team house a library of components that the entire company uses every single day.
The developers have been tasked with creating a simple product description component, that houses the title, photo of the product and add to cart button. The initial code looks like this:
<div class="listing">
<div class="imageContainer">
<img alt="" class="stockImage" src={this.props.imageSrc}/>
</div>
<div class="details">
<span>{this.props.saberName}</span>
<div role="button" tabindex="0" class="btn"
aria-label="Add to Cart">Add to Cart</div>
</div>
</div>
Notice how instead of using a <button>
, the development team decided to use ARIA role of button and tabindex="0". Simple enough first time through. Now the development team has new requirements that require the product name to be a heading and to also add a list of item highlights underneath. They add in the changes like so:
<div class="listing">
<div class="imageContainer">
<img alt="" class="stockImage" src={this.props.imageSrc}/>
</div>
<div class="details">
<span role="heading" aria-level="4">{this.props.pd}</span>
<section class="list" role="list">
<div class="li" role="listitem">
{this.props.descOne} </div>
<div class="li" role="listitem">
{this.props.descTwo}</div>
<div class="li" role="listitem">
{this.props.descThree}</div>
</section>
<div role="button" tabindex="0" class="btn" onClick=
{this.addCart} aria-label="Add to Cart">Add to Cart</div>
</div>
</div>
We start to see the markup get a little murky since a lot of ARIA attributes have been added to our HTML. Now let's add in a curveball to this scenario!
Let's say two of the developers on the team leave to go to a new team, and two new developers are added. These two new developers have no real experience with accessibility and are tasked with updating this same component again.
This time the update says we need to add CSS dots to the left of the list items, and then the add to cart button will now be a CSS image as well, instead of "Add to Cart" text. They make the changes like so:
<div class="listing">
<div class="imageContainer">
<img alt="" class="stockImage" src={this.props.imageSrc}/>
</div>
<div class="details">
<span role="heading" aria-level="4">{this.props.pd}</span>
<section class="list" role="list">
<span class="dot"></span>
<div class="li" role="listitem">
{this.props.descOne} </div>
<span class="dot"></span>
<div class="li" role="listitem">
{this.props.descTwo}</div>
<span class="dot"></span>
<div class="li" role="listitem">
{this.props.descThree}</div>
</section>
<div role="button" tabindex="0" class="btn"
onClick={this.addCart}></div>
</div>
</div>
The component has been updated, and is in its final state. Hurray right?! Well, maybe not. Let's take a look at what happened during this story.
Untangling The Web Of ARIA
The above story is one seen far too often. Development teams don't know true semantic HTML, and instead search for accessibility solutions to not using proper HTML. What we end up with is a complete mess of a component that actually ends up with more accessibility issues than when we started.
The new developers who made the final changes were not aware that by adding a <span>
for a dot actually broke semantics for lists. They also did not realize by removing text from the <button>
and using CSS image instead, removed the semantic text for the button as well. If this component would have used semantic HTML from the beginning, these problems are not as common.
If that component could have been completed with semantic HTML it would look this this:
<div class="listing">
<div class="imageContainer">
<img alt="" class="stockImage" src={this.props.imageSrc}/>
</div>
<div class="details">
<h4>{this.props.pd}</h4>
<ol class="list">
<li>{this.props.descOne}</li>
<li>{this.props.descTwo}</li>
<li>{this.props.descThree}</li>
</ol>
<button class="btn" onClick={this.addCart}>
Add to Cart</button>
</div>
</div>
See how much cleaner and simpler the HTML code looks now! The best part is, all of the accessibility for the list, button and heading are now baked into the semantic HTML tags.
Problem With ARIA First Development
There are many problems with using an ARIA first mindset in the web development process but these remain the top ones:
- ARIA code is murky and can be very difficult to understand
- It is not as maintainable as using semantic HTML
- Run the risk of adding MORE accessibility issues by accident
- It can override native semantics
- Some ARIA attributes are not fully supported by all assistive technologies
In Summary
Too often development teams now turn their heads at learning semantic HTML because they believe it is at the bottom of totem pole of knowledge. That could not be farther from the truth. The story told in this article is one seen far too often and simply could be avoided with a semantic HTML first mindset.
I am a web developer at heart, and I know there are scenarios where ARIA is needed in order to make content accessible. If you choose to use ARIA, just make sure you are following proper ARIA practices. And for those scenarios that don't require ARIA, don't use it and you can avoid a tangled web of ARIA in your daily development.
Top comments (4)
I think perhaps the example isn't right as a
<span>
within arole="listitem"
is fine as far as I am aware?I am assuming that the
<span>
for the dots is not going to interfere with a screen reader due to some weird CSS choices however.What is broken is that the first
listitem
doesn't have a space between two attributesclass="li"role="listitem"
so that will break the list.I mean, none of it actually matters as you are 100% right that the first example is a steaming pile of XXXXX and the second example is elegant and accessible, but I was just trying to understand what the problem was with the
<span>
?Anyway, ignore my ramblings, I love the article and the message, that bit just jumped out at me so I thought I would ask 🤣!
Have a much deserved ❤🦄!
You are 100% correct! I meant to put it outside the listitem and into the containing div with the role of list. That then causes the semantic problems. Great catch! Thank you!
That makes sense!
No problem, I am glad it was that as I was seriously questioning myself! 🤣
As I said, great article, I hope at least one person listens and avoids ARIA spaghetti!
Nice description of the problem. +1 for semantic html - much more readable and succinct. I wonder if one day we might see law suit succeed when someone describes ARIA-first as spaghetti html, as has happened with spaghetti code.
And it is like spaghetti code - where the only people/person who understand it have long gone and new developers coming in are afraid to change anything for fear of breaking something. Build for resilience!