Roles: from "last resource" to "powerful tool"

Roles: from "last resource" to "powerful tool"

Role attribute is often used as a workaround for accessibility while in reality it gives an added layer of meaning to your code.

Here we're talking about semantics. Every element, well, every semantically meaningful element, has its own role. An <ol> is meant to be considered as an ordered list, an <img> should be considered as an image, a <button> should be seen, by technologies that read and try to interpret the code, as a button. But what about a <div> or a <span>? Or what about a <button> that should be considered as a menu-item?

Role, before aria role

As briefly introduced, all semantic elements have their own roles. Technologies in general leverage roles to understand what's the purpose of that element in your document, both for content and structure. Encountering a <heading> for a browser is like telling it: "hey, after these words begin a chapter/topic, and by the way, what's inside the heading is what I'll talk about in that chapter".

Sometimes also the interaction is affected by the semantic meaning the element has. For example, a link is triggered by "Enter", while a button by both "Enter" and "Spacebar".

For every technology this aspect is crucial, but often is not fully understood by us mere humans. Or at least until we discover first-hand how technology interprets our code. A screen reader, just to make the banalest example, reads what's inside your document adding a lot of additional information, such as describing what a not-visually-impaired user can see but a screen reader can only describe. Encountering a <ul>, for example, a screen reader announces that you are about to read a list of items, tells you how many items and proceeds to read them one by one, clearly distinguishing when it goes from one to the following. You can easily figure yourself that representing a <ul> by creating new lines preceded by a dot image is really different.

Luckily, if you have a semantic element there's no need to specify its role, since it already has one. There are a few exceptions, and we'll see them later.

Role attribute

You can imagine the role attribute like a magical badge: you wear a chef badge and you begin cooking like Gordon Ramsay, you wear a basketball player badge and you can slam dunk... You're Gordon Ramsay and you wear a basketball player badge? Bam! now you have the skill of Shaquille O'neal. That's right: even if you have a semantically meaningful element, when a different role is specified, that element is seen and considered what the role specifies.

Explicit roles override implicit ones.

You have great power, here, and I bet you already know what comes from great powers... right Spidey?

The dark side

Now you have the possibility of using whatever you want and letting various technologies think you're coding in the right way. Yes, you can, or... you could, but should you?

Obviously not. You'll end with lesser readable code, more convoluted and thus more error-prone. Stylistically there's a huge difference between neat code and garbage. If you do, you should be ultra sure of what you're doing: in 90% of cases, if you're ending using a different role than the implicit one, something went wrong.

The light side

Roles are however really important for, obviously, giving meaning to those elements that don't have any implicit role by themselves: divs, spans...

And if you have noticed, before I said "90%" of cases. Why not 99.9% or 100%? Because some roles go beyond the simple semantic meaning of the element, adding a more deep, specific meaning and functionalities. In these cases it's just good to go over the implicit role.

Role categories

Landmark roles

You should use them to identify all your document's different sections: screen reader users use them a lot to understand where they are and to jump directly to a certain location in a breeze.

Document structure roles

Are used to describe what the various parts of content are. Many of them have their HTML5 semantic counterparts, so I suggest you use these properly crafted ones whenever possible. Document, image, table... you got it, right?

Widget roles

These are used to define common interactive patterns, often in conjunction with JS for giving them additional functionalities. Menu, combobox, gridcell, scrollbar... as above, use appropriate HTML tags whenever possible.

Live region roles

Live Region roles are meant for elements with dynamic content that will likely change. You can have a more in-depth view of this topic by reading the article Aria-live: announce DOM changes.

Window roles

These are for sub-windows to the main document: think of modals and pop-ups. Hold tight, an article is coming soon.

Beyond the role: special attributes

Specifying a role allows (and sometimes requires) the developer to use specific attributes: a button (or a role="button") can have various additional attributes relative to being pressed, that an image (or a role="image"), for example, doesn't. It's out of scope to list them all here, so I suggest you pick a single role and begin exploring what allows you to do in the documentation.

No roles

Finally, there are times when you have elements for aesthetic purposes only or for whatever reason you want to remove elements' semantics from assistive technologies while leaving their content still available. You can achieve this with role="none" or role="presentation" (they are synonyms). Mind that applying this to an element, this behaviour propagates to all the element's children.

Be aware, however, that it doesn't work for focusable elements, including links and inputs, or anything with a specified tabindex attribute.