and
. Use the right semantic elements as much as possible!
— Beth Fraser
Simplest #a11y advice I’ve ever received: the div is your last resort. Is this your main content? There’s a tag for that. Is it your header? That’s got a tag, too. The div isn’t bad; it just doesn’t mean anything. That means you certainly don’t need it for something clickable!
Assume your content has a specific meaning and try to find the tag for that meaning. If it doesn’t, then the div (or span) is what you want! The div does have a place. That place is not what many tutorials would have you believe.
— E.J. Mason
JavaScript is imperative for creating truly accessible custom interactive components.
Even though you can get away with creating “functional” interactive components such as a CSS-only modal overlay or a disclosure widget using the infamous checkbox hack, it is almost always guaranteed that those CSS-only components are not truly accessible.
When you create an interactive widget, that widget is most likely to have a state. A disclosure widget is either “open” or “closed” (or “expanded/collapsed”). That state is exposed to screen reader users using ARIA attributes (e.g. aria-expanded="true/false"
), and when a user interacts with the widget, the state changes, and that change needs to be conveyed to the user. JavaScript is needed to do that. I made peace with this fact two years ago when I needed to create an accessible tooltip for one of my clients.
JavaScript is also needed to add keyboard functionality to custom components (e.g. tabs in a tabbed interface need to be navigable by arrow keys, and a disclosure widget needs to be operable using SPACE and ENTER keys).
Side note: Even though JavaScript is a requirement for creating interactive custom components, in order to make sure that your content is inclusive of all users regardless of their context, you can, and probably should — whenever possible — make sure that they can consume that content when JavaScript is not available. In fact, you should never assume that your users will have JavaScript, as there are plenty of reasons why they might not. This is why progressive enhancement is the most accessible strategy for building for the Web. I would even go as far as saying that it is a requirement, in some cases, for creating inclusive documents and components.
Progressive enhancement is an inclusive strategy for building for the Web.
There seems to be a misconception among many developers that just because JavaScript is required to make an interactive component accessible then you cannot possibly build it with progressive enhancement as an approach. The reason for that is that those developers think that Progressive Enhancement is anti-JavaScript. That is a fallacy.
Progressive enhancement is about layering — starting with a resilient base — semantic HTML! — and then layering styles (CSS) and functionality (JavaScript!) on top as appropriate.
What progressive enhancement can help achieve is creating a resilient base layer of content which can be built to be accessible, even when the CSS and/or JavaScript are absent.
From the first day that I learned about progressive enhancement, it became my go-to strategy for building Web interfaces. Now I can’t imagine creating for the Web another way. And when I started building with accessibility in mind, I was convinced that it is the most sensible approach to developing for the Web.
Let’s take a Tabs component again, as an example. In a tabbed component, you have a series of tabs that control their respective content panels. The user can navigate between these panels by activating the tab they want. Tabs require JavaScript to be operable and accessible. But what if JavaScript does not work? If the Tabs were not progressively enhanced — if they were built with the assumption that JavaScript would always be there, then the component will fail to function and the content in all the hidden panels would likely be completely inaccessible.
But if you think about Tabs from a progressive enhancement point of view, you’ll want to consider what the content inside of it would look like had it been only created using HTML — without the CSS that adds the Tabbed UI affordances, and without the JavaScript that makes the component function.
In a situation where there is no JavaScript, you may think of the tabs and panels as a series of sections, each with a heading and content. These sections may or may not have a table of contents at the top of the page. This would be the default “view”, and is what the user gets by default when the JavaScript doesn’t work.
A tabs component may be enhanced from a series of sections, each with a title and some related content.
A tabs component may also be enhanced from a series of sections, each with a title and some related content, with a table of contents preceding these sections.
Then, when the JavaScript runs, you can enhance those sections by changing their layout and display, and adding the required interactivity. The way I would do it is I would probably add a style hook I want in the markup, and then I’d use that to change the layout of my sections knowing that the JavaScript has run and the Tabs will be operable and interactive.
When you shift accessibility to the left of your process, using progressive enhancement as a development strategy makes even more sense. Pretty much every single non-native interactive component I have built over the past year has been enhanced from a basic non-interactive component. Start with HTML first. Utilize everything it has to offer to provide an accessible basic experience. Then enhance with CSS and JavaScript when they are available.
Progressive enhancement. Because sometimes your JavaScript just won’t work.
Be prepared.
— @sil
Design does not always dictate implementation.
One of the most common ways I see semantics broken is when they are derived from the visual design. Because the visual design does not always describe the type of content it is representing.
Headings are a perfect example here. In a recent talk I gave , I showed an example from one of my latest client projects, where the page was designed in a way that a main heading for the page was seemingly non-existent, when in fact it wasn’t. It was just not styled like a large level one heading normally would.
The main title of the page that describes the content in the page’s main section is positioned and styled in a way that (unintentionally) disguises the fact that it is a main heading. Even though it is styled like a level 6 heading, it is implemented as a level 1 heading in the markup to represent what it really is.
Thinking about the document structure and screen reader user expectations, I knew the page needed to have a main heading. While I had to provide a heading for screen reader users only for some other pages where one was visually absent, in this particular case the heading was already there, it was just styled to look different. So it looked like the page didn’t have a main heading, but in reality it did.
Looking at the page through the lens of accessibility and keeping the HTML layer — semantics and structure — in mind, changed the way I saw the page, and fundamentally changed how I ended up coding it.
So just because a component or element looks a certain way doesn’t mean that it is. And just because it doesn’t look a certain way, doesn’t mean that it isn’t.
The same is true for interactive UI patterns. The same pattern may create a different experience depending on the context it is in. And often times the context defines how a pattern should behave, what the user experience should be like, and that, in turn, determines what the underlying semantics should be, and that drives implementation.
In the same project I just mentioned, there was a seemingly simple UI pattern that turned out to be quite an interesting UX and accessibility challenge. The following image is a screenshot of that component:
The featured videos component in my recent client project shows a video on the left with a playlist of videos on the right. Clicking on any of the video titles on the right would load the video on the left; but it would not autoplay it. (Note that the content in this screenshot is dummy.)
In order to implement this video player, I needed to know how it worked, so I can mark it up in a way that conveys its semantics and functionality to screen readers properly.
Even though the list of video titles on the right looks like a list of links, it is not really a list of links , because a link is supposed to take you somewhere, but these “links” don’t. Clicking on a video title would load that title in the player on the left. So it is an interactive element that performs an action and that is not a link. Therefore, and even though their appearance doesn’t show it, these titles are actually buttons .
Then there was the question of what happens when a title is clicked? does the video autoplay? If it does, then the button should probably also pause the video, making it a type of a toggle button. But if you play/pause a video from the title button, you’d want to associate that button to the play/pause buttons inside the video itself, which can be a challenge given that the video could be a YouTube video, or a Vimeo video, or self-hosted. And if you don’t autoplay the video, should you move focus to the iframe
after the button is clicked?
After reviewing the intended UX and testing with screen readers, I ended up implementing it as a tabs component, with all tabs controlling the one panel containing the video.
I had never thought about a tabbed interface with multiple tabs controlling the same one panel before. But the context of this component and the UX of it triggered a train of thought and UX considerations that drove the final implementation.
So one of the things that I learned from this component was that the UX drives the implementation. ARIA comes with a lot of attributes that enable us to create different UI patterns in different contexts, and sometimes all we need to do is modify the pattern a little bit to work in the context it is in.
It’s weird that we still derive the semantics from a visual design instead of the other way around.
The visual design is different per context while the core semantics are not.
— Rik Schennink
Just because it is technically accessible, doesn’t mean it is inclusive.
You can build something that is technically accessible but isn’t inclusive. That element or component may have all the buttons you want and you may be able to navigate it using a keyboard and use it with a screen reader, but did you really take your user’s needs and expectations into consideration when you made the decisions about how and what of that element should be exposed and interacted with?
In his talk “Inclusive by Design ”, Derek Featherstone, accessibility advocate and designer, talks about how he and his team built an accessible video player for an organization that they were contracted by. The video player had lots of buttons and was tested for technical accessibility over many phases.
But then when the time came and the component needed to be used by users with different disabilities, they realized that, even though they had built the perfect accessible video player, that video player was not truly inclusive — it was missing certain functionality that made using the player easier for a group of users, such as a Rewind or Fast Forward button. Derek and his team had also made assumptions about how all users would be using the video player, and forgot about the users that were using an older version of a screen reader and who were therefore missing important announcements that were supposed to help them operate the video player. So after several iterations and tests with various users, they ended up adding features to the video player that would take many more disabilities into account, and expectations that those users would have of the player, and that made it far more inclusive and tremendously improved its user experience.
Derek’s talk is full of such good examples that emphasize the importance of including your users early in the design process , and making sure that you embrace diversity by default. The idea is that if you’re designing something for me, I should have a reasonably meaningful way of participating in that thing. I should be represented in that somehow.
“Nothing about us, without us.” – Michael Masutha
At the end of the day, it is always about the user.
As you develop with real user experiences and inclusivity in mind, you’ll soon realize that a design pattern can be built in more than just one way. And there are quite a few things in accessible design that are opinionated.
Modal overlays are a great example. Regardless of being an annoying UI pattern, there are quite a few discussions around how they should be implemented and how they should behave once they are opened: Should you focus the first focusable element inside the modal? What if there is no focusable element? What if the first focusable element is the close button? Would you want the modal overlay to prompt a closing action as soon as it’s opened? (Of course not.) What if the first focusable element is an input field asking the user for their email address? Is it appropriate to prompt the user for their personal information without context first? (Also of course not.)
At the end of the day, no matter what decision you end up making, it should always be about the user. So getting the user and/or a more diverse team involved in the design and development process is crucial in building truly inclusive Web interfaces.
But what if you can’t? What if you don’t have access to such an environment or team? What if, like me, you’re a solo developer who often joins teams that usually don’t have users or disabled people involved?
When in doubt, ask for help.
If you can’t do it yourself, you can seek the experience and advice of other people who can. And it is very important for you to be open to constructive feedback.
There are quite a bunch of wonderful (and sometimes understandably grumpy) accessibility experts in our field who want the Web to be and become more accessible. Most of them have been doing free work like giving free advice and sharing their valuable knowledge in various forms — writing articles and books, making video courses, giving talks and workshops, etc. And there is a lot that we can learn from them. And most of them welcome questions and inquiries (paid and free).
Some of my go-to experts are (in no particular order):
You’d do well to spend some time reading the ARIA specifications and guidelines, and trying to get acquainted with as much about accessibility as you can, before asking for help. After all, these kind people may be able to help us, but they shouldn’t have to do our work for us — at least not for free.
Final Words
Accessibility isn’t easy. And often times it is downright hard. But that comes with the territory. Designing for humans is hard. And accessibility is, at the end of the day, all about and all for humans.
We may not get it completely right, and there may always be room for improvement — especially as more users use our products and consume our content, but one thing I know is that that should never discourage us. Almost everything can be improved in one way or another. The most important thing is to be open to feedback and to be empathetic enough to care about our users and try our best to make their lives easier with the (powerful) tools we have at our disposal.
Use HTML. Enhance with CSS. Leverage the power of JavaScript. And include your users in your design process as early as possible. And always look at your work through the lens of inclusion. This will take you far ahead. Then learn more, iterate, and improve. And don’t forget, we’re all just temporarily abled .