Accessibility Engineering — Let the Web Platform do the Work

Being a web developer is hard. You're handed some written requirements and, if you're lucky, a visual design. You start work on the new feature: You add HTML elements, style them with CSS, and implement business logic with JavaScript. You need to think about usability, web security, page speed, data management, and so on.

You take a deep breath and tell yourself: “I can do this!”

Your project manager comes in and asks: “The website will also be accessible, right?” You panic and start to research web accessibility. You're flooded with information. Some of it contradicting. You ask ChatGPT for help. It shows you overcomplex code ridden with ARIA attributes. You sigh, thinking: “That's a lot of work!”

I have good news for you: Accessibility doesn't have to be this exhausting. It can actually be quite simple and, I dare say, beautiful. All you need to do is embrace the web platform and let it do the work!

Lines of code are projected onto a woman who's looking at the camera. Photo: © ThisIsEngineering / pexels.com

We'll take a quick look at the basic tools of the web and how to use them efficiently. Then I'll give you several specific examples of web features with accessibility baked in.

The Basic Tools of Accessibility Engineering

The web platform is a collection of technologies developed as open standards by the World Wide Web Consortium and other standardization bodies. These technologies include HTML, CSS, JavaScript and WAI-ARIA. These building blocks of the web enable us to design websites that are accessible to all people.

Then why are so many web developers struggling with accessibility? I think there are two main reasons:

  • Over-reliance on external libraries.
  • Insufficient experience with native web features.

Most junior developers nowadays learn web development based on frameworks like Angular, React or Vue.js. They learn everything about components and data management, but hardly familiarize themselves with native HTML elements and advanced CSS features.

I don't blame any of them! Modern JavaScript frameworks and UI libraries offer powerful features that help us implement complex web applications. But they are another level of abstraction. They take us away from the essential building blocks of the web. So what should you do?

HTML First and The Rule of Least Power

The rule of least power is a design principle that suggests choosing the least powerful language suitable for a given purpose. What does this mean for web developers? If you can do something with HTML, use HTML. Need to adapt the styling? Use CSS. If you can't do it with HTML and CSS alone, use JavaScript and WAI-ARIA.

Native HTML elements are built to work on multiple browsers and with different types of assistive technology, like screen readers. They're usually more robust and reliable than custom solutions. Next time you start to implement a new feature, look for a solution in the following order:

  1. HTML
  2. CSS
  3. JavaScript
  4. WAI-ARIA
  5. External Libraries

As a first step, I always search for a native solution on MDN Web Docs. If I can't do something with HTML and CSS alone, I start to research the proper use of ARIA attributes and JavaScript to create an accessible solution. The ARIA Authoring Practices Guide (APG) provides all the information you need.

Why are external libraries last on the list? Because they create an additional dependency for your project. Once you've commited to using a UI component library, you're usually stuck with it. That's why you should make sure to pick an accessible UI library. Go read my “Checklist for Accessible UI Component Libraries”.

The Current State of the Web

The web platform is constantly evolving. New HTML elements, CSS properties and Web APIs are specified and implemented by browsers every day. Initiatives like Interop 2024 help to improve the interoperability of the web.

For web developers, it's way easier and straightforward to create accessible websites today than it was 10 years ago. I admit, not everything can be done with HTML and CSS alone. Right now, you still need ARIA and JavaScript to implement a tab list or custom tooltips.

But I want to focus on the bright side! Let's take a look at some native HTML features that make it very easy and convenient to create robust, accessible websites.

Examples of Native HTML Features

The button element: A Powerful Allrounder

Chances are, the button element is older than you! It was first introduced in the HTML 4.0 specification in December 1997. This means, buttons have been around for quite a while. But still, many web developers underestimate this powerful and versatile HTML element. Some even think it's a good idea to use a div element instead. The horror! 😱

Maybe you're thinking: “Alright, Romeo! Why are you so in love with the button element?” Let me answer with the short description by MDN:

The <button> HTML element is an interactive element activated by a user with a mouse, keyboard, finger, voice command, or other assistive technology. Once activated, it then performs an action, such as submitting a form or opening a dialog.

The button element was designed to work well for all users. You can click on it with a mouse. You can focus a button with the TAB key and activate it with the Enter or Space key. When you navigate to the button using a screen reader, it will be able to tell you that this is a button that can be activated.

Browsers also apply a default styling to HTML buttons. Some web developers might find this annoying, because they have to override these styles with CSS. They might pick the div element instead and slap a click event handler on it, thinking that's enough. Well, it's not!

There's a big difference between button and div elements! A button will trigger the click event handler for all types of user interaction: mouse, keyboard, screen reader, and so on. The div element, on the other hand, will only trigger on mouse or touch interaction. To turn a div into an accessible button, you need to:

  • Add a tabindex to make it keyboard focusable.
  • Show a visible focus indicator when the button receives focus.
  • Add key event handlers for the Enter and Space key.
  • Add a role attribute to tell screen reader users it's a button.

Wow, that's a lot of work and code bloat! An implementation using a native button instead will always be easier to read and maintain. If you're still not convinced, go read my article “3 Ways how Web Developers also benefit from Accessibility”.

That's already a lot of text about buttons. But there's one more argument I'd like to make: Native buttons are still gaining more superpowers!

The latest upgrade is thanks to the new Popover API. You can use the popovertarget attribute to turn the button element into a popover control button. Check out this menu button demo (currently only works in Chromium browsers):

There are so many use cases for buttons with attached popovers: Menus, tooltips, date pickers, etc. If you're new to the topic, you can take a look at the following articles I've written:

But we're not done yet! The next button upgrade will arrive with the (currently experimental) Invoker Commands API. This API provides a way to declaratively assign behaviors to buttons, like opening or closing a modal dialog. Awesome! 🥰

Oh, what a coincidence! Dialogs are the next native HTML feature I want to talk about.

The dialog element: Always on top

Dialogs are an integral part of modern web user interfaces: From simple prompts for confirming an action to content-heavy windows. The native dialog element makes it super easy to open an accessible modal dialog on top of the other page content.

The dialog element is accessible by default. When you use the showModal() method to open a modal dialog, the following happens:

  • The browser automatically moves focus to the first interactive element inside of the dialog.
  • A screen reader will announce that the new content is part of a dialog.
  • While the modal dialog is active, the content obscured by the dialog is inaccessible to all users. This means that keyboard users can't leave the dialog with the TAB key, and a screen reader's virtual cursor is not allowed to leave the modal dialog as long as it remains open.
  • Users can close the modal dialog with the ESC key.
  • On close, keyboard focus returns to the control that initially activated the dialog. This allows keyboard and screen reader users to continue browsing from where they left off.

Of course, you don't have to use the native dialog element. You could also implement a custom, accessible dialog using ARIA and JavaScript. But why would you? Come on! Be a smart web developer and let the web platform do the work. 😉

If you're unfamiliar with the native dialog element and want to know more, go read my article “Why you should use the Native Dialog Element”.

Form Controls: The Good and the Bad

Far too often, web developers use custom form controls to meet design needs – neglecting accessibility in the process. You can do better! Modern browsers enable us to apply custom styling to most native form controls. This way, we can create accessible web forms with a consistent look across all platforms.

Native form controls like input or select are accessible by default. They receive keyboard focus and can be activated with Enter or Space, e.g., to mark a checkbox as checked. They communicate their role and current state to screen readers.

The following demo shows an accessible web form with custom styles for the native select list and radio buttons:

Unfortunately, not all native form controls can be easily adapted with custom styles. Mozilla has a great article on Styling web forms, which I highly recommend. They categorize native form controls into three groups: “The good”, “The bad”, and “The ugly”.

In my opinion, the native elements for text inputs, radio buttons, checkboxes and simple select lists are very easy to style. There is no reason to use custom elements instead. Unless you have a masochistic disposition. Read my article “Create Accessible Web Forms with Custom Styling” for more information.

Now, what about the rest? Several native form controls have internals that can't be styled in CSS alone. These include the color picker, date picker, file picker, and the drop-down list of the select element. In these cases, I understand the need for custom components. Just make sure they're accessible.

Lucky for us, the select element will soon get an important upgrade. A customizable version of the element is officially in Stage 2 in the WHATWG, with strong cross-browser interest and a prototype available in Chrome Canary. Read this Chrome blog post for more information. 🤩

Disclosure and accordion widgets with native HTML

The native details HTML element creates a disclosure widget in which information is visible only when the widget is toggled open. The content of the nested summary element provides the label for the disclosure widget. The perfect HTML elements for a FAQ page or an expandable info section in an article.

<details> <summary>What is HTML?</summary> HTML is the standard markup language for web pages, defined by the W3C and WHATWG. </details>

Historically it wasn't possible to change the display type of the details element. This restriction has already been relaxed in Chromium browsers, allowing you to use grid or flex layouts. The article “More options for styling <details> includes a really cool demo for an exclusive accordion.

Conclusion

Alright. This article turned out longer than I had intended. 😂

I hope it helps you on your journey to becoming an accessibility engineer. Native HTML is powerful and (mostly) accessible by default. If you keep this in mind, you'll be alright.

Posted on