Demystifying Screen Readers: Accessible Forms & Best Practices

This is the 3rd post in a small series we are doing on form accessibility. If you missed the 2nd post, check out Managing User Focus with :focus-visible. In this post we are going to look at using a screen reader when navigating a form, and also some best practices.

What is a Screen Reader?

You may have heard the term “screen reader” as you have been moving around the web. You might even be using a screen reader at this moment to run manual accessibility tests on the experiences you are building. A screen reader is a type of AT or assistive technology.

A screen reader converts digital text into synthesized speech or Braille output, commonly seen with a Braille reader.

In this example, I will be using Mac VO. Mac VO (VoiceOver) is built-in to all Mac devices; iOS, iPadOS, and macOS systems. Depending on the type of device you are running macOS on, opening VO could differ. The Macbook Pro that is running VO I am writing this on doesn’t have the touch bar, so I will be using the shortcut keys according to the hardware.

Spinning Up VO on macOS

If you are using an updated Macbook Pro, the keyboard on your machine will look something like the image below.

You will start by holding down the cmd key and then pressing the Touch ID three times quickly.

MacBook Pro Keyboard with steps on how to start mac voiceover.

If you are on a MBP (MacBook Pro) with a TouchBar, you will use the shortcut cmd+fn+f5 to turn on VO. If you are using a traditional keyboard with your desktop or laptop, the keys should be the same or you will have to toggle VO on in the Accessibility settings.. Once VO is turned on, you will be greeted with this dialog along with a vocalized introduction to VO.

Welcome to VoiceOver dialog when opening up voiceover.

If you click the “Use VoiceOver” button you are well on your way to using VO to test your websites and apps. One thing to keep in mind is that VO is optimized for use with Safari. That being said, make sure when you are running your screen reader test that Safari is the browser you are using. That goes for the iPhone and iPad as well.

There are two main ways you can use VO from the start. The way I personally use it is by navigating to a website and using a combination of the tab, control, option, shift and arrow keys, I can navigate through the experience efficiently with these keys alone.

Another common way to navigate the experience is by using the VoiceOver Rotor. The Rotor is a feature designed to navigate directly to where you want to be in the experience. By using the Rotor, you eliminate having to traverse through the whole site, think of it as a “Choose Your Own Adventure”.

Modifier Keys

Modifier keys are the way you use the different features in VO. The default modifier key or VO is control + option but you can change it to caps lock or choose both options to use interchangeably.

VoiceOver utility to change the modifier keys.

Using the Rotor

In order to use the Rotor you have to use a combination of your modifier key(s) and the letter “U”. For me, my modifier key is caps lock. I press caps lock + U and the Rotor spins up for me. Once the Rotor comes up I can navigate to any part of the experience that I want using the left and right arrows.

VoiceOver rotor feature showing the Headings navigation.
Using the Rotor in VoiceOver

Another neat way to navigate the experience is by heading level. If you use the combination of your modifier keys + cmd + H you can traverse the document structure based on heading levels. You can also move back up the document by pressing shift in the sequence like so, modifier keys + shift + cmd + H.

Using the Heading Level Shortcut with VoiceOver

History & Best Practices

Forms are one of the most powerful native elements we have in HTML. Whether you are searching for something on a page, submitting a form to purchase something or submit a survey. Forms are a cornerstone of the web, and were a catalyst that introduced interactivity to our experiences.

The history of the web form dates back to September 1995 when it was introduced in the HTML 2.0 spec. Some say the good ole days of the web, at least I say that. Stephanie Stimac wrote an awesome article on Smashing Magazine titled, “Standardizing Select And Beyond: The Past, Present And Future Of Native HTML Form Controls”.

The following are 5 best practices to follow when building an accessible form for the web.

  1. Make sure that you are using a form element. Forms are accessible by default and should be used over div’s at all times.
<form>
  <!-- Form controls are nested here. -->
</form>
  1. Be sure to use the for and id attributes on label’s and input’s so that they are linked. This way, if you click/tap the label, focus will shift to the input and you can start typing.
<label for="name">Name:</label>
<input type="text" id="name" name="name" required aria-required/>
  1. If a field is required in order for the form to be complete, use the required attribute and the aria-required  attribute. These will restrict the form from being submitted. The aria-required attribute explicitly tells the assistive tech that the field is required.
<input type="text" id="name" name="name" required aria-required/>
  1. Use the, :focus, :focus-within and :focus-visible CSS pseudo classes to manage and customize how a user receives focus.
form:focus-within {
 background-color: #cfffcf;
}

input:focus-within {
 border: 10px solid #000000;
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
 outline: 2px solid crimson;
 border-radius: 3px;
}
  1. A button is used to invoke an action, like submitting a form. Use it! Don’t create buttons using div’s. A div by definition is a divider. It has no inherent accessibility properties.

Demo

Navigating a Web Form with VoiceOver

If you want to check out the code, navigate to the VoiceOver Demo GitHub repo. If you want to try out the demo above with your screen reader of choice, check out Navigating a Web Form with VoiceOver.

Screen Reader Software

Below is a list of various types of screen reader software you can use on your given operating system. If a Mac is not your machine of choice, there are options out there for Windows and Linux, as well as for Android devices.

NVDA

NVDA is a screen reader from NV Access. It is currently only supported on PC’s running Microsoft Windows 7 SP1 and later. For more access, check out the NVDA version 2024.1 download page on the NV Access website!

JAWS

“We need a better screen reader”

– Anonymous

If you understood the reference above, you are in good company. According to the JAWS website, this is what it is in a nutshell:

“JAWS, Job Access With Speech, is the world’s most popular screen reader, developed for computer users whose vision loss prevents them from seeing screen content or navigating with a mouse. JAWS provides speech and Braille output for the most popular computer applications on your PC. You will be able to navigate the Internet, write a document, read an email and create presentations from your office, remote desktop, or from home.”

JAWS website

Check out JAWS for yourself and if that solution fits your needs, definitely give it a shot!

Narrator

Narrator is a built-in screen reader solution that ships with WIndows 11. If you choose to use this as your screen reader of choice, the link below is for support documentation on its usage.

Complete guide to Narrator

Orca

Orca is a screen reader that can be used on different Linux distributions running GNOME.

“Orca is a free, open source, flexible, and extensible screen reader that provides access to the graphical desktop via speech and refreshable braille.

Orca works with applications and toolkits that support the Assistive Technology Service Provider Interface (AT-SPI), which is the primary assistive technology infrastructure for Linux and Solaris. Applications and toolkits supporting the AT-SPI include the GNOME Gtk+ toolkit, the Java platform’s Swing toolkit, LibreOffice, Gecko, and WebKitGtk. AT-SPI support for the KDE Qt toolkit is being pursued.”

Orca Website

TalkBack

Google TalkBack is the screen reader that is used on Android devices. For more information on turning it on and using it, check out this article on the Android Accessibility Support Site.

Browser Support

If you are looking for actual browser support for HTML elements and ARIA (Accessible Rich Internet Application) attributes, I suggest caniuse.com for HTML and Accessibility Support for ARIA to get the latest 4-1-1 on browser support. Remember, if the browser doesn’t support the tech, chances are the screen reader won’t either.

DigitalA11Y can help summarize browser and screen reader info with their article,  Screen Readers and Browsers! Which is the Best Combination for Accessibility Testing?

https://support.apple.com/guide/voiceover/with-the-voiceover-rotor-mchlp2719/mac

https://www.w3.org/TR/wai-aria/

https://www.w3.org/WAI/standards-guidelines/aria/

https://support.google.com/accessibility/android/answer/6283677?hl=en

https://support.google.com/accessibility/android/answer/6283677?hl=en


Demystifying Screen Readers: Accessible Forms & Best Practices originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

A Step-By-Step Guide To Building Accessible Carousels

You can spot them on every other homepage: carousel widgets with auto-rotating content. Those who use them want to show more content within a limited space. At the same time, they aim to present the most important messages as prominently as possible. However, if design and development do not receive proper attention, you will be at the highest risk of creating usability and accessibility issues.

This particularly affects people with cognitive, motor, or visual impairments, for whom using the complex design pattern is usually even more challenging. Whether you call it an "eye candy" or "devil’s spawn", if you want to implement the carousel in a user-friendly and accessible way, a whole range of requirements is to be considered.

“Should I Use A Carousel?”

As widely used as they are, carousel widgets have a bad reputation among UX professionals. They are ignored by users (Nielsen Norman Group), only 1% interact with a carousel at all, and 89% of them only with the first slide (Eric Runyon). Jared Smith even responds to the question "Should I use A Carousel?" by saying, "Seriously, you really shouldn't." Others state that there isn’t one answer. You have to consider various factors, such as function, design, platform (desktop or mobile) and, most importantly, context. For whatever reason you include a carousel on a website, make sure it is user-friendly and accessible.

Accessible Implementation

For a carousel to be accessible, it is essential that all users can perceive the widget and its components and that they can easily navigate it using a mouse, touch gestures, a keyboard, a screen reader, and any other assistive technology. The rotation of the slides must not interfere with users' ability to operate the carousel or use the website as a whole.

The W3C’s WAI-ARIA working group provides guidance on implementing an accessible carousel in its ARIA Authoring Practices Guide (APG). This article is based on those recommendations and wants to create a profound understanding of elements and ARIA attributes applied and their impact on users.

Auto-Rotating

I assume we have all been there at some point: Constantly changing content can be rather annoying. For some people, however, uncontrolled rotation can be absolutely critical:

  • People need different times to read content.
    If the available time is not enough, auto-advancing carousels can become very frustrating. It’s not very satisfying to just be able to skim the text before new content appears without any request.
  • Some people, especially people with cognitive impairments such as attention deficit disorder, may experience moving content distracting.
    The movement could prevent users from concentrating and interacting with the rest of the website. People within the autistic spectrum may even have to leave such a page entirely.
  • Screen reader users may not be aware of the rotation.
    They might read a heading on "slide 1" and execute the keyboard command for "read next item." Instead of hearing the next element on "slide 1", the screen reader announces a text from "slide 2" — without the person knowing that the element just read out is from an entirely new context.

WCAG 2.1, therefore, requires the possibility to stop movement (2.2.2 Pause, Stop, Hide).

  • Add a "Pause" or "Stop" button if you cannot give up auto-rotation at all.
    The "Pause" button is the minimum solution (if the movement does not end automatically after 5 seconds). In addition, usability experts recommend the following:
  • Pause auto-rotation as long as a slide is being hovered.
    There is usually a correlation between the mouse position and the user’s interest in a piece of content. Don’t risk a slide change a few milliseconds before a person activates a link and then ends up on the wrong page and, to make things worse, not realizing that this was not the intended one.
  • Stop the rotation permanently when users are setting focus on interactive elements using a keyboard or interacting with the carousel.
    An action such as actively changing slides also indicates that the user might be interested in the content. People may temporarily explore other parts of the page but possibly want to come back. Furthermore, you make keyboard navigation easier if the carousel stops as soon as a control receives focus.

Visibility

For all of us, user interface elements are intuitively easier to use if we can perceive them well. For people with visual impairments, however, this aspect is crucial.

  • Ensure sufficient contrast.
    Most often, icons are used to indicate the controls: simple arrows for advancing the slides as well as the widely used dots for selectively fading in. However, these icons often have poor contrast against the background, especially when placed on images. The easiest way to avoid contrast issues is to position the icons outside the slides.
  • Provide a visible focus indicator.
    People navigating with a keyboard need to be able to see which interactive element they are currently focusing on. Often design merely (if at all) provides a slight and barely discernible change in color of the controls. If color is the only way to indicate focus, both colors (the one used for non-focused and focused state) must meet at least a contrast ratio of 3.0:1 with each other. This minimum contrast requirement also applies to the icon against its background and to other kinds of focus indicators (e.g., a border that indicates the focus state of a button).
  • The size of the controls affects their visibility as well.
    Besides, with a reasonable target size combined with sufficient distance between interactive elements, you reduce the risk of accidentally activating a nearby button or a linked slide. This not only benefits people with limited dexterity but also minimizes errors when using mobile devices.
  • Indicate the current position within the set of slides.
    It is not the only option, but often this is done by highlighting one of several progress dots. To ensure that people with color deficiencies can access visual information, you must not rely on color alone but use a color-independent indicator, for example, a filled and unfilled dot.

Activation With A Simple Pointer Input

Many people are used to moving slides on touch devices by swiping. But there are also users who cannot perform this gesture because of their impairment or because of the assistive technology they use. In addition to swiping, enable users with an alternative way of navigating (WCAG 2.5.1 Pointer Gestures).

Provide interaction with a simple pointer input (e.g., simple click or tap). That means if there are no slide picker controls to display content directly, you need to implement "Previous" and "Next" buttons.

Structure, Semantics And Labelling

The carousel widget is designed primarily for two-dimensional, visual use. For screen reader users who do not see the carousel as a whole, it is much harder to understand the composition of controls and content. These users have different perspectives when using a website. They explore content linearly, tab through interactive elements, and use shortcuts for navigation. The challenge is to provide a meaningful structure and semantics and inform users about controls and slides in a way that enables them to build a mental model of the widget. Use semantic markup for different sections, controls, and content and proper labeling to ensure good orientation.

Regions And Groups

Using the HTML element <section> (or role="region") with an accessible name, you can set a generic landmark and thus mark smaller regions of a page. Landmarks provide a way to identify the structure of a web page to screen reader users and help them with orientation. Using a screen reader, you can display these sections in a table of contents and use specific keyboard shortcuts for landmarks to move focus to the corresponding content.

When navigating to the landmark, the assistive technology announces the name and type of the section, for example: "[name] — region". In browse mode (exploring content with arrow keys), the screen reader tells users when they enter or exit a region. They will hear something like "[name] — region" or "out of region". (This output in browse mode is currently well-supported by the screen reader NVDA, but unfortunately, with JAWS, users have to set screen reader settings accordingly.)

role="group" is intended to form a logical set of items as a group. Since it is not a landmark, the group is not included in a landmark listing displayed by the user. For that reason, use this role in contrast to role="region" for less important sections of a page. You could use role="group", for example, to group (custom) form controls (compare <fieldset> and <legend> in HTML) but it is not limited to this.

With role="group", it is also necessary to use the role with an accessible name. The screen reader will convey the boundaries of the group by announcing something like "[name] — grouping" or "out of grouping," and the assistive technology will inform users about the start and end of the group (in this case also JAWS in the default setting).

The following applies to role="region" and role="group": When the first interactive element within the region or group receives focus, the screen reader will announce its name and role, plus the role and label of the focused control.

The Carousel Container

Currently, there is no specific HTML element or ARIA role to mark up a carousel. However, you can still convey semantic information to make the existence of the carousel, its sections, and the meaning of the controls clear and understandable to non-visual users. That will help them better adapt to the widget and its interaction patterns.

role="region|group" + accessible name

An easy way to make non-visual users aware of the carousel is to use a landmark or a group role: To get there, use the <section> element (or role="region") or role="group" for the container that encompasses all the carousel elements (including the carousel controls and slides). In addition, provide an accessible name that identifies the carousel as such.

Carousel container marked with a landmark:

<div role="region" aria-label="Carousel">
    <!-- Slides and controls -->
</div>

Screen reader output when encountering the widget: „Carousel — region“

The W3C Authoring Practices go beyond this basic markup and recommend using the aria-roledescription attribute:

role="region|group" + aria-roledescription + accessible name

With aria-roledescription, you create an even more specific output for screen reader users. You thus define the meaning of the container more precisely.

Code sample (HTML): Carousel container marked with a landmark with a specified meaning

<div role="region" aria-roledescription="carousel" aria-label="Design patterns">
    <!-- Slides and controls -->
</div>

Screen reader output: "Design patterns — carousel" instead of (without using aria-roledescription) "Design patterns — region." In the previous example, we have seen a more generic accessible name ("Carousel"). With role="region", this has resulted in the output: "Carousel — region".

aria-roledescription changes the way a screen reader announces the role of an element. This allows authors to define a localized and human-readable description for a role. The screen reader announces the value of aria-roledescription (a string provided by the author) instead of the original role. It overrides the role to which the attribute is applied. aria-roledescription should only be used on elements that have a valid implicit or explicit (ARIA) role.

Back to our carousel, this means instead of region or grouping (you can also use role="group" instead of role="region"), the value of aria-roledescription is read out by the assistive technology. Note: If the aria-roledescription property is set to "carousel", you should not set the aria-label property to "carousel" because this would be redundant.

The ARIA specification recommends the attribute mainly for clarifying the purpose of non-interactive container roles such as group or region. Otherwise, use it with great caution:

“Do not use aria-roledescription to change the way a role is announced, if it will prevent the user from knowing what to do with it.”

Léonie Watson

The Slide Container

Just as you communicate the boundaries of the carousel as a whole, you can do the same for the slides. Each slide represents simply a smaller entity within the "carousel" composite.

role="group" + aria-roledescription + accessible name

Container for slides marked as "group" with a specified meaning:

<div role="group" aria-roledescription="slide" aria-labelledby="carousel_item-1_heading">
  <h2 id="carousel_item-1_heading">Modal dialogs</h2>
  <!-- Some more content -->
</div>

Screen reader output: „Slide — heading level 2 — Modal dialogs“

In this example, the heading of the slide serves as the accessible name of the group. The aria-labelledby property is set to the id of the heading. You could also use the aria-label attribute to convey the position within the set of slides, for example, "1 of 3". In particular, that makes sense if no unique name is available to identify the slide.

Again, if you set aria-roledescription to "slide", the aria-label property should not be set to "slide" to avoid redundancy.

The Slides

Slides that are not visible should be hidden, not only visually but from all users (including users of assistive technology). You can either use CSS (display: none or visibility: hidden) or the HTML hidden attribute.

If you truly hide the slides that are not visible, you should not use list markup for the whole set of slides. Screen readers do announce the number of list items (which may seem helpful) but will ignore hidden ones. Concerning the carousel, list markup would not result in an output of the total number of list items but just the visible ones. If only one slide is visible, that wouldn’t be very helpful.

The Container For The Controls

What about the container for the controls? It also encompasses a set of items. Because of this, it is reasonable to apply role="group" to it. And again, the group needs an appropriate group name.

role="group" + accessible name

Container for controls marked as "group" with a specified meaning:

<div role="group" aria-label="Slide controls">
    <!-- Slide controls -->
</div>

Screen reader output: „Slide controls — grouping“

In this context, the accessible name (the group name) reflects the purpose of the controls, for example, "Slide controls" or "Choose a slide".

The ARIA Authoring Practices refer to this implementation as a "grouped carousel". Another approach is described as "tabbed carousel". Following the "tabbed" pattern, you would use role="tablist", role="tab" for the controls and role="tabpanel" (instead of role="group") for the slide container. Don’t use aria-roledescription in this case. The appropriate ARIA properties are specified in the tab pattern.

The Controls

Slide picker controls allow users to display a specific slide. They visually present the total number of slides and indicate the current position within the set. It is rather popular to use "dots" for that purpose.

Operable Keyboard Controls

All controls must be operable with the keyboard. Use the native button element for controls of the grouped carousel. That involves the "Previous" and "Next" buttons, the "Pause" button, and the slide picker controls.

If you cannot use native HTML, add semantic information by applying an explicit ARIA role (role="button") to the clickable div or span element. Use tabindex="0" to include the element in the tab sequence. Furthermore, you need to incorporate JavaScript that provides interactions expected for a button (activation with Space and Enter ). Be aware that ARIA roles do not cause browsers to provide keyboard behaviors.

Grouped controls

<div role="group" aria-label="Slide controls">
  <button aria-label="Show slide 1 of 4"> 
      <!-- SVG icon -->
  </button>
  <!-- Some more controls -->
</div>

Screen reader output: „Slide controls — grouping — Show slide 1 of 4 — button“

The Accessible Name Of The Controls

Choose an appropriate accessible name (text alternative) in context with the group name. Regarding the above example, the screen reader would announce: "Slide controls — grouping — Show slide 1 of 4" — button" when focusing on the first control in the group (or "Slide controls — grouping — Pause — button" if the first control is a "Pause" button).

Assuming the group name is "Choose a slide," then the heading of the corresponding slide would also be a reasonable label for the button in this context. Instead of using the aria-label attribute, you could also specify the label using visually hidden text.

Along with the group name and the slide picker elements, the "Previous," "Next," and "Pause" buttons need an accessible name. That means do not forget about the text alternatives for these icons either.

Semantic Markup Of The Active Control

Do not just indicate visually but also semantically which control does represent the currently displayed slide. You can use aria-disabled="true" for this purpose. In this case, aria-disabled is preferable to the HTML attribute disabled. Unlike disabled, a button with an aria-disabled attribute is still included in the tab sequence of the page. You may also use the aria-current property set to "true".

Focus Order

For a webpage to be accessible using a keyboard or assistive technology, it is important to ensure a proper focus order. That is the order in which you tab through interactive elements. An appropriate order generally means that it follows the visual flow of the page. Users can navigate in a logical and predictable way without loss of orientation.

By default, the tab order is set by order of the elements in the source code (more precisely, in the DOM). That means that the order in which you write the HTML will affect the focus order when navigating with the keyboard. The DOM order also affects the reading order, that is, the order in which screen reader users in browse mode linearly explore content using the arrow keys (non-interactive content included).

The DOM and, with it, the focus sequence should match as closely as possible to the visual order of the page. In this way, sighted keyboard users can easily follow the sequence.

Content changes that precede the current focus cause issues with sequential navigation since screen reader users will not know about such changes (apart from dynamically displayed status messages implemented using live regions). Users need to navigate backwards to reach those interactive elements, which makes navigation more difficult.

A Proper And Understandable Focus Order For A Carousel

Many carousel implementations are intended to visually display the controls below the slides:

  1. Previous
  2. Slide
  3. Next
  4. Pause
  5. Slide Controls

If this order matches the order of the elements in the DOM, both the activation of "Next" and the activation of the slide controls will cause a content change (display of a new slide) before the triggering control. That is, users need to navigate backwards if they want to explore the content of the slide with the screen reader or follow a link on the slide.

DOM Order

The focus order is easier to use, and the reading order is more meaningful if the controls (at least the "Pause" button and the slide controls) are positioned in the DOM before the changing slides. If you still want the controls to be visually positioned below the carousel, use CSS for this purpose. When in doubt, a good focus and reading order for the carousel is more important than the optimal conformity with the visual order:

  1. Pause
  2. Slide controls
  3. Previous
  4. Slide
  5. Next

or

  1. Pause
  2. Slide controls
  3. Previous
  4. Next
  5. Slide

Notice that people working with magnification software will locate the "Pause" button more quickly if it is also visually positioned at the beginning of the carousel. They do not see the carousel as one (depending on the magnification level) but might explore the content by moving the keyboard focus or the mouse pointer, which results in repositioning their viewport.

Pause And Previous/Next Buttons

When activating the Pause / Play and Previous / Next control, the focus has to remain on the button. That allows sighted keyboard users to repeatedly press the button and perceive the changing content at the same time.

The Keyboard Navigation For "Tabbed Carousels"

If you prefer following the "tabbed carousel" pattern, allow users to navigate with arrow keys within the set of controls. In addition, ARIA markup must correspond to the tab pattern (unlike the "grouped carousel") to make screen reader users understand the expected operation based on the information announced by the screen reader.

Working Example

Complete carousel widget:

<div role="region" aria-roledescription="carousel" aria-label="Tips & Techniques">
  <div role="group" aria-label="Slide controls">
    <button aria-label="Stop auto-rotation">
      <!-- SVG icon -->
    </button>
    <button aria-disabled="true">
      <span class="hide-element">Show slide 1 of 3: Hiding Accessibly</span>
      <!-- SVG icon -->
    </button>
    <button aria-disabled="false">
      <span class="hide-element">Show slide 2 von 3: Accessible Contrasts</span>
      <!-- SVG icon -->
    </button>
    <button aria-disabled="false">
      <span class="hide-element">Show slide 3 von 3: Semantics, WAI-ARIA and Assistive Technologies</span>
      <!-- SVG icon -->
    </button>
    <button aria-label="Previous slide">
      <!-- SVG icon -->
    </button>
    <button aria-label="Next slide">
      <!-- SVG icon -->
    </button>
  </div>
  <div role="group" aria-roledescription="Slide" aria-labelledby="carousel-item-1__heading" id="carousel-item-1">
    <h2 id="carousel-item-1__heading">Hiding accessibly</h2>
    <!-- Further slide contents -->
  </div>
  <div hidden role="group" aria-roledescription="Slide" aria-labelledby="carousel-item-2__heading" id="carousel-item-2">
    <h2 id="carousel-item-2__heading">Accessible Contrasts</h2>
    <!-- Further slide contents -->
  </div>
  <div hidden role="group" aria-roledescription="Slide" aria-labelledby="carousel-item-3__heading" id="carousel-item-3">
    <h2 id="carousel-item-3__heading">Semantics, WAI-ARIA and Assistive Technologies</h2>
    <!-- Further slide contents -->
  </div>
</div>
Wrapping Up
  1. Add a button to pause or stop all movement.
  2. Ensure that controls have sufficient contrast (meet WCAG’s color contrast requirements).
  3. Provide a visible focus indicator.
  4. Don’t rely solely on swiping. In addition, provide interaction with a simple pointer input (e.g., simple click or tap).
  5. Provide semantic markup and labeling to ensure that screen readers can identify the carousel as a whole, the slides, and the set of controls. For the "grouped carousel", use role="group" with an aria-label or aria-labelledby attribute. For the carousel container, you can also use a landmark (role="region" with an accessible name) instead of role="group".
  6. The aria-roledescription attribute allows you to specify the meaning of the container tagged with role="region" or role="group".
  7. If you go for the "tabbed carousel", use the ARIA attributes specified in the tab pattern. Ensure keyboard navigation within the set of "tabs" can be operated with the arrow keys.
  8. All controls must be keyboard operable and require meaningful text alternatives for icons.
  9. Ensure a proper focus order. It is recommended to position at least "Pause" and slide controls in the DOM before the slides, even if this order may differ slightly from the visual tab order.
Conclusion

This article describes one way of implementing carousel widgets in an accessible way. Even W3C working groups provide different approaches in the ARIA Authoring Practices Guide (APG) and the W3C Accessibility Tutorial (see also a discussion on GitHub and the comment by Jason Web regarding user testing of "tabbed carousels" and focus management). The important thing is:

  • Be familiar with semantic markup options and their impact on users.
  • The objective is to provide a predictable and understandable way of operating the widget, also for non-visual users.
  • Test with a keyboard and a screen reader. This will show most clearly whether you have met your goal or not.
  • If you do not have the resources to implement a carousel in an accessible way or if it is just the wrong pattern, better explore alternatives, and you might notice the benefits they entail.
“Carousels are complex components, and making complex components accessible adds more complexity.”

Léonie Watson

Note: This article was first published in German on tollwerk.de in April 2022.

Useful Resources

Comparing JAWS, NVDA, and VoiceOver

A screen reader is an important accessibility tool for people with no or limited vision. People who are blind or those with low vision can use a screen reader to navigate the computer. Screen readers will read contents on the screen and explain to the user what is on the page. Screen readers allow people to use the computer for daily tasks.

There are many screen reader software available for people through their operating system or through open source projects.

A 2021 research by WebAim found that from 1568 responders, more than 53.7 percent of people surveyed used JAWS on Windows, more than 30.7 percent of people used NVDA on Windows and little over 6.5 percent of people used VoiceOver on macOS.

JAWS and NVDA for Windows and VoiceOver for macOS are the most popular screen readers people use.

First, I should clarify that this article will be written from my point of view. To give background, I have been a front-end developer at a non-profit for people with learning differences for over three years. I, along with my colleagues, seek to make our projects more accessible every day. I am not visually impaired and do not use these tools on a regular basis. For work, I have a Mac machine and test accessibility using VoiceOver.

Here is my planned testing methodology:

  1. Navigate the page by heading, until “Accessibility APIs” section.
  2. In the “Accessibility APIs” section, read the content and the unordered list inside.
  3. TAB to hear focusable items in the unordered list.
  4. Jump to the Search field.
  5. TAB to hear a few items in the navigation section

To find similarities and differences between them, I decided to test a set of steps with each screen reader on a Wikipedia page about screen readers. I will browse the web with Chrome for my tests. Testing all screen readers on the same page and browser will reduce the amount of variables and keep the tests consistent.

JAWS

JAWS is an acronym for Job Access With Speech and is the most widely used screen reader in the world. It is only available on Windows. Depending on the plan and features, JAWS can be purchased anywhere from $90 yearly license all the way to $1605 for perpetual license.

JAWS has predefined keyboard commands to navigate the web. Full list of keyboard commands can be found on their website.

Demonstration

JAWS Demo

In the beginning of the demo, I am clicking on H key on my keyboard to go to the next heading. JAWS is moving down the page, reading me the headings along with their level.

Later in the video, I am clicking on number 2 and number 3 on my keyboard to have JAWS read Heading Levels 2s then later Heading Levels 3s. This is a great feature because we can move down the page and sections by heading level and get a better sense of the page layout.

When I reach the “Accessible APIs” section, I press the DOWN ARROW key until the third item in the unordered list.

Later in the demo, I am clicking on the TAB key for JAWS to read to me the next focusable item on the page, which is inside this list. I click TAB until I reach a focusable element in another section.

Then I press F key to focus on the search field, which JAWS reads to me.

Then I click on TAB and JAWS focuses on the navigation elements that are on the side of the page.

Pros & Cons

Pros:

  • JAWS is more customizable than other screen readers.
  • There are more options to navigate through the page.
  • JAWS is industry standard.
  • Widely used, which means there are lots of user to user support.

Cons:

  • JAWS is more complicated to use than NVDA or VoiceOver.
  • Some commands are not intuitive.
  • There are a lot more commands for the user to learn.
  • More learning curve for users.
  • JAWS is also not available on the Mac, which limits its users.
  • Costs anywhere between $90 – $1605 for the user.
  • JAWS has different key commands for desktop and laptop which may make it harder for users to transfer knowledge and may cause confusion.

NVDA

NVDA, or NonVisual Digital Access, is available on Windows only. Users need to download the software from NVDA’s website, NVAccess. This software is free to download but does not come already installed on Windows machines. NVDA is the second most popular screen reader in the world according to WebAim’s 2021 survey.

Like other screen readers, NVDA has defined keyboard commands to navigate the web. NVDA’s full keyboard commands can be found on their website.

Demonstration

NVDA Demo

In the demo I am clicking on H key on the keyboard to go to the next heading. First, NVDA reads me Heading Level 1, which is “Screen reader”. Then NVDA goes to read Heading Level 2s and 3s.

When I reach “References” I begin to click on TAB on my keyboard for NVDA to focus on next focusable items.

After focusing on a few items on the list, I click ENTER and go to the New York Times page.

Pros & Cons

Pros:

  • Overall, I found NVDA was able to provide me with information on the screen.
  • The out-of-the-box keyboard commands were easy to use and easy to learn.
  • NVDA is open source, which means the community can update and fix.
  • NVDA is free, which makes it an affordable option to Windows users.

Cons:

  • NVDA is not available on the Mac, which limits its users.

VoiceOver

VoiceOver is the screen reader used in Mac. VoiceOver is only available on Mac not available in Windows. VoiceOver is free and is already installed on the computer, which removes barriers because this is part of the computer setup and the user does not have to download or purchase any additional software.

VoiceOver has defined keyboard commands to navigate the web. VoiceOver’s full keyboard commands can be found on their website.

Demonstration

VoiceOver Demo

In the demo, I am on a Wikipedia page and I am clicking on the VoiceOver Command (which is Control+Option) along with Command+H to navigate through the headings. VoiceOver reads the headings in order, starting from Heading Level 1, “Screen Reader”, to Heading Level 2, “Contents”, to Heading Level 3, and so on.

When I reach the “Accessibility APIs” section, I click on VoiceOver Command plus the RIGHT ARROW, to tell VoiceOver that I want it to read this section. Later I am clicking on the VoiceOver Command plus the RIGHT ARROW on my keyboard, to navigate the section.

When I get on to the third item on the unordered list, I press TAB on my keyboard to focus on the next focusable element.

I press TAB a few times, then I press VoiceOver Command plus U, to open the Form Control Menu. In the menu, I press DOWN ARROW until I hear the “Search Wikipedia” option. When I hear it, I click ENTER and the screen reader focuses on the form field. In the form field, I press TAB to navigate to the navigation section.

Pros & Cons

Pros:

  • VoiceOver is easy to use and learn.
  • VoiceOver’s commands are intuitive.
  • Free tool that comes installed in every macOS device.

Cons:

  • VoiceOver is also not available on Windows, which limits its users.
  • VoiceOver is not an app and can only be updated when Apple releases macOS update.

Key Takeaways

A screen reader is an important accessibility tool for people with no or limited vision. Screen readers allow people to use the computer for daily tasks.

There are many screen reader softwares available. In this article I compared JAWS, NVDA, and VoiceOver.

Here is a comparison chart overview of the three screen readers:

JAWSNVDAVoiceOver
Operating SystemWindowsWindowsmacOS
Price$90 – $1695FreeFree
# of users30%50%6%
Ease of UseHardEasyEasy

I found that for basic screen reader testing, most screen readers follow a similar keystroke pattern and knowledge from one screen reader can be used for others.

All screen readers have their pros and cons. Ultimately, it’s up to user preference and also the operating system they use to determine which screen reader software is best for them.

Previously: “Small Tweaks That Can Make a Huge Impact on Your Website’s Accessibility” (2018), and “Why, How, and When to Use Semantic HTML and ARIA” (2019), “15 Things to Improve Your Website Accessibility” (2020), “5 Accessibility Quick Wins You Can Implement Today” (2022).


Comparing JAWS, NVDA, and VoiceOver originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

&lt;article&gt; vs. &lt;section&gt;: How To Choose The Right One

“Do I use a <section> or an <article> element?” I have had to ask myself this question an unhealthy amount of times whenever I have to group content in a container element.

A conversation I had on Twitter led me to research this question and ultimately to write on it. It was a conversation with Grace Snow where I shared an approach to writing HTML that I love to use. I love to write out my HTML structure (boxes) first and with no content to ensure I am not thinking of styling while I write my HTML. She then spotted that I might be making problematic use of the section and article elements in my sincere attempt to be semantic.

It turns out that to choose between section and article, we need our content. In fact, to determine if our content is narrowed down enough to those two, we need our content.

We can build a mental model that ensures we make the best decision every time by taking our content into consideration.

Let’s take a deep dive in!

Document Semantics

HTML passes two related but distinct information to user devices. The first is the visual presentation information, which tells the device how to display the document by default.

The second is known as semantic information or, simply, semantics. It conveys “meanings” in the document, i.e., each element’s purpose and the relationship between them. In this sense, the spec would say that an element “represents” something. So, when you see “represents” in the spec, what follows is the semantic information embedded in the element.

The h1 element reveals the presence of these two sets of information. The visual presentation information for the h1 element, when encountered by browsers, is why it appears bold and with a larger font size than the rest of the document. The semantic information that the h1 represents is that it is the highest rank heading for its section.

Sighted users can gleam the semantic meaning from devices like the browser by observing the visuals. For headings, we can differentiate based on differences in font size and weight, or in the case of lists, the presence of bullet point markers or numbered markers. For users who do not rely on sight, the semantics are only accessible through options or devices that allow them to request that the semantic information be announced in other ways that may not be visual. These options and devices are generally called assistive technology.

HTML prescribes some elements that convey implicit meaning to browsers which browsers can extract to the accessibility API, making it available to assistive technologies that, in turn, interpret this meaning to users. This meaning gives users a wholesome sense of the webpage they are visiting, such as document structure and navigation assistance, or in this instant case, both document structure and navigation assistance.

However, it is not only elements that directly wrap text content that carries semantic information. Elements meant for grouping other elements also carry some meaning; in some cases, it may be meaning we want to communicate.

Does My Grouping Play A Semantic Role?

This first step in our mental model is to question if grouping the content as we are about to do is necessary for the document structure to make sense. Broken down, I would ask myself in this kind of manner:

  • Is there any possibility the content of this block shares something in common that adds some sense to my document structure overall when it is read together?
  • If I were to describe my document structure to a person without showing it to them, would I mention that there is that particular grouped area for them to appreciate the document structure?

If the answer to these questions is “no,” then you may have a situation where a <div> could be appropriate, as Scott O’Hara notes. Reading Scott’s article could help you further examine the role your grouping plays and even formulate a better set of questions than mine. I do not intend to cover the <div> element in this article as Scott sufficiently covers it. I only intend to state that first, you must confirm that the grouping you are making is influenced by document structure. If it is, you can proceed to interrogate further to determine if it is an <article> or <section>.

To be clear, I do not mean that the grouping must only be influenced by document structure for you to start to consider <article> or <section>. It is enough that it is one of the possible reasons. For instance, it is possible for content in your grouping to share a distinct design or language and, at the same time, influence the document semantics.

What Semantic Role Does My Grouping Play?

We have now decided that the grouped content serves some function in describing the document. The next step is to determine which of the semantic meaning already carried by the article or the section element most accurately describes what function your grouped content is intended to serve in the document structure.

What The HTML Spec Say

Let us take a look at the primary source of authority on HTML and start to form our understanding of the section and article elements and their inherent semantic meaning.

The HTML Living Standard says of the article element:

The article element represents a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g., in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent content item.

As relates to the section element, the HTML Living Standard defines it this way:

The section element represents a generic section of a document or application. A section, in this context, is a thematic grouping of content, typically with a heading...

Examples of sections would be chapters, the various tabbed pages in a tabbed dialog box, or the numbered sections of a thesis. A website’s home page could be split into sections for an introduction, news items, and contact information.

To help narrow it further, the specs offer this clue on when to use the section element:

...A general rule is that the section element is appropriate only if the element’s contents would be listed explicitly in the document’s outline.

The linked specs give quite elaborate examples. However, it is safe to say that the choice is seemingly heavily subjective. Authors must actively decide if the particular group they have come up with is “complete” and “independently distributable,” in which case the choice would be an article or if it is a “thematic grouping of content,” in which case the choice would be a section. Let’s consider some tasks.

If you were to build a blog like Smashing Magazine, which of these elements would you use to wrap the portion of the landing page that contains the list of all blog posts teasers? In that wrapped portion, what element would wrap each blog post teaser? If you click on one of the blog post teasers and land on the expanded post page, which elements would wrap up the blog article?

If you were to build Twitter, would you wrap each tweet fed into the users’ timeline in an article because they are “self-contained” and “in principle, independently distributable”? Or would you wrap them in a section because they are “a generic section of an application”? Or perhaps, in this case, a div is semantically appropriate? Still taking the Twitter example, is your timeline container a section of the whole Twitter application, or is your timeline an article within your Twitter application? Or perhaps everything is just cake, and nothing is real.

We will return to apply our mental model to these two scenarios.

Understanding What The Specs Mean

I reckon the reason for the seeming confusion is the mental model we have. At least that was the case for me.

The article element was not so-named after a written article. I wrongly assumed that it was, and perhaps you might have too. I literally just learnt that an article element existed and assumed that blog articles are so important on the web that the WHATWG decided to make an element dedicated to wrapping blog posts like this one. It felt intuitive to me, but I was wrong. I guess that is why web standards exist. Intuitions are not always uniform.

It turns out that in the Oxford English Dictionary and other dictionaries, one of the definitions for the word article is “a particular item or separate thing.” This is the sense in which the specs use the article element. It is right there in the spec’s definition of the article element, but as I said, that is not how I generally use the word “article.” In fact, dictionaries give the first definition of an “article” as a written work.

So, while the spec clearly says what sense it is used in, we still do not think of it that way.

To make it more adjust our thoughts, Bruce Lawson gives the best anecdote to understand the article element:

I gave my usual answer: think of <article> not just as a newspaper article or a blog post, but as an article of clothing — a discrete entity that can be reused in another context. So your trousers are an article, and you can wear them with a different outfit; your shirt is an article and can be worn with different trousers; your knee-length patent leather stiletto boots are an article (you wouldn’t wear just one of them, would you?).

It means what an article represents is content that can be taken out of the document and away from the immediate surrounding content, dropped somewhere else, say on another page, and still make total sense as it is grouped.

In the same way that you could use an article, such as a table lamp (an independent content group), to improve the aesthetics of your living room, and it would complement your sofa, tv console, curtains, and so on (immediate surrounding content). Yet, if you were to take your table lamp into your room, and it was simply placed at your bedside or your workstation, it would still be identifiable as a complete lamp.

The section element, on the other hand, represents “a thematic grouping of content,” meaning that a section is a part of a larger group without which it may not necessarily stand to make complete sense alone. It may stand alone, but in the theme of your content overall, it is less likely to be standalone. As the spec put it, “Examples of sections would be chapters, the various tabbed pages in a tabbed dialog box, or the numbered sections of a thesis. A website’s home page could be split into sections for an introduction, news items, and contact information.”

This is why a section would usually have a heading, providing a sort of call back to what part of the larger document the section relates to.

Let us go back to our lamp analogy. Our lamp itself makes sense as an item, but in reality, it has different parts that could technically be separated but really should not. I could take off the umbrella-shaped hood of my lamp, take the light bulb out, take off the base, and take off the upright stand. Together, they make up a lamp but, taken apart, not quite. If you are presented with the umbrella-shaped hood of a lamp, you are likely to think, “What is this from? Where is the rest of it?” If you are presented with the light bulb, you are likely to think, “Where does this go?”

Let’s Group Some Content

A Blog Website Landing Page

Firstly, let us take the example of a blog website. Our blog is the Smashing Magazine. Let us take a look at our landing page.

Here are the major areas on our landing page:

  • Header with Site navigation,
  • Main Area,
  • Footer with Topic Navigation.
<header>
    <nav>
        <!--     Website navigation goes here -->
    </nav>
</header>

<main>
    <!--     We would group the content that should go here     -->
</main>

<footer>
    <nav>
        <!-- Topic navigation goes here     -->
    </nav>
</footer>

These are groups that already have elements to represent them. So, we are not deciding between section and article for these.

In our Main Content, these are the identifiable groups:

  • Selected Articles,
  • Newsletter Subscription,
  • Components and Guides,
  • Latest Posts,
  • Smashing products and offerings,
  • Smashing conferences,
  • External articles from community members.

What element should wrap these grouped content? Let us apply our mental model. For each of these content groups, we follow this mental model.

  • Does grouping this content play a role that may help explain my document structure?
    • If it does not, then I can use a div.
    • If it does, play a role and proceed to consider if the role matches a section or an article.
  • What role does it play in my document structure?
    • Is the content of this group thematically related such that it helps to understand the outline of my document? If it is, then it is possibly a section.
    • Is the content of this group one that contains content that I can take out and redistribute to other pages while it does not totally tie to my document theme and outline? If it is, then it is possibly an article.

I encourage you to grab a piece of paper and make your grouping before proceeding to see mine. This way, we can compare how we think of each content group’s role on our page.

Now let’s build the skeletal grouping for our Smashing Magazine:

  • Selected Articles
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • Newsletter Subscription
    Does it play a role in my document structure? Hmm. Well, it is not exactly necessarily within the central theme of my landing page, so I am doubtful about this one. I’d just say “no.” Verdict: div.
  • Components and Guides
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • Latest Posts
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • Smashing products and offerings
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • Smashing conferences
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • External articles from community members
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.

Here is what my Smashing Magazine landing page looks like now:

<header>
    <nav>
        <!--     Website navigation     -->
    </nav>
</header>

<main>
    <section>
        <!--     Selected articles     -->
    </section>

    <div>
        <!--     Newsletter subscription     -->
    </div>

    <section>
        <!--  Components and guides    -->
    </section>

    <section>
        <!--     Latest posts -->
    </section>

    <section>
        <!--     Smashing products and offerings -->
    </section>

    <section>
        <!--     Smashing conferences     -->
    </section>

    <section>
        <!--     External articles from community members     -->
    </section>
</main>

<footer>
    <nav>
        <!-- Topic navigation     -->
    </nav>
</footer>

We all might adjudge the role some items play differently. The “Newsletter Subscription” area, for instance. I would not outline “Newsletter Subscription” in my document outline, nor would I care to encounter it on a document outline for a page I visit. Yet again, if it were Substack, a platform for newsletters, I would definitely see how an area to subscribe to the newsletter would be a section. And while I have used a div here, it could as well have been an aside, but, of course, that is not why we are here today. The point is how we adjudge our content guides our decision.

I guess my point is your decision would be marginally better provided you interrogate and justify the role you want your content group to play in each case. You would have consciously put effort into making your web content understandable for users and other developers that would encounter your technical debt.

An Article Post On A Blog Website

So, we have clicked on one blog article from the “Selected Articles” area and have expanded that article to its own page. This specific blog article you are reading, how is it grouped? Again, here is our base template:

<header>
    <nav>
        <!--     Website navigation     -->
    </nav>
</header>

<main>
    <!-- This article is wrapped here -->
</main>

<footer>
    <nav>
        <!-- Topic navigation     -->
    </nav>
</footer>

Do you wrap it in an article, do you wrap it in a section, or perhaps a div?

Would you break this article itself into smaller grouped bits? Maybe a bunch of sections or a couple of articles? Are there redistributable parts of this article or parts that you would expose to the document outline?

I would refrain from saying what I arrived at, but I would love to know what you would use. Take a note of your answers as we shall revisit this later on.

A Web Application: Twitter

So, we have one more exercise, a web application, specifically Twitter.

  • Is the timeline container a section of the whole Twitter application, or is your timeline an article within your Twitter application, or is it a div?
  • Would you wrap each tweet fed into the users’ timeline in an article because they are “self-contained” and “in principle, independently distributable”? Or would you wrap them in a section because they are “a generic section of an application”? Or perhaps, in this case, a div is semantically appropriate?

If I apply the mental model, below is the way how I would do it:

My timeline is a part of my document outline, and yet, to an extent, it can be independently distributed. I could take my timeline out, and it would stand well alone. It seems like it could be viable for a section or an article. So, I question further, what do I really intend? Do I want it to function for redistribution or as a part of my application? If you use Twitter, you would agree that your timeline is more of an integral part of your homepage than it is redistributable. Here I would settle for a section.

For each tweet in my timeline, it would be an article. This is because each tweet is not thematically connected to the next tweet on my timeline such that I could say it can be a part of an outline. So, tweets are not sections. They are “self-contained” and “in principle, independently distributable.” You can even click a tweet to enter a new world with comments and quote tweets, and so much more.

Truly, and indeed, if you walk your way through the div-soup of the Twitter page, nested in, there is a nice pretty section just sitting there, as it should be. This section holds your timeline. And if you proceed deeper into the section, and further down a serving of divs, you can pick up an article holding each tweet. This is where I confess that I let out a tiny scream when I discovered that my thoughts matched what Twitter did.

This inspection of Twitter also shows how the presence of divs does not mean that semantic meaning has been sacrificed or lost.

Nesting sections And articles And Other Groups

You can nest these elements within each other. You probably already figured that by now after looking at the Twitter example.

divs, articles, and sections can go into each other without necessarily breaking accessibility. If you apply the mental model, you can question each nesting you are about to make and group accordingly.

Take the example of this blog post. I did not answer how I would wrap it when I asked a few paragraphs ago. Here is what I could do:

I could wrap this whole article you are reading in an article. Then I would further nest the large chunks of this article into sections because I want each portion to be really divided up for easy understanding. So far, this is what this blog post you are reading could look like:

<header>
    <nav>
        <!--     Website navigation     -->
    </nav>
</header>

<main>
    <article>
        <h1>Article versus section: Making your choice count in the larger context of accessibility</h1>

        <section>
            <h2>Quick summary</h2>
            <!--  paragraphs go here    -->
        </section>

        <section>
            <h2>Introduction</h2>
            <!--  paragraphs go here    -->
        </section>

        <section>
            <h2>Document Semantics</h2>
            <!--  paragraphs go here    -->
        </section>

        <section>
            <h2>Does my grouping play a semantic role?</h2>
            <!--  paragraphs go here    -->
        </section>

        <section>
            <h2>What semantic role does my grouping play?</h2>
            <!--  paragraphs go here    -->
            <h3>What the HTML specs say</h3>
            <!--  paragraphs go here    -->
            <h3>Understanding what the specs mean</h3>
            <!--  paragraphs go here    -->
        </section>

        <section>
            <h2>Let's group some content</h2>
            <!--  paragraphs go here    -->
            <h3>A bog website landing page</h3>
            <!--  paragraphs go here    -->
            <h3>An article post on a blog website</h3>
            <!--  paragraphs go here    -->
            <h3>A web application: Twitter</h3>
            <!--  paragraphs go here    -->
        </section>

        <section>
            <h2>Nesting sections AND articles</h2>
            <!--  paragraphs go here    -->
        </section>

        <!--     Rest of article continues here     -->
    </article>
</main>

<footer>
    <nav>
        <!-- Topic navigation     -->
    </nav>
</footer>

Notice how I give my sections appropriate headings since I have decided to use section? Recollect that the spec says a section should typically have a heading. Also, recall that you make sections if you think they should feature in your document outline. As such, a heading would provide the text to feature in the outline.

If there is a need for it, your sections and articles could have other grouped content in them. For instance, you could have a header to hold your section’s heading or a footer to hold information about a section, such as links to related documents, etc. If you will, the “Further reading” area of this post could be wrapped in a footer.

As for main, you are restricted to using it only when it is hierarchically correct, i.e., if it is a direct child of html, body, div or form. In any case, you are restricted from using more than one main element without the hidden attribute.

How section And article Are Exposed

So far, we have looked at how to group content but only from the viewpoint of developers. How is how our grouping exposed to readers?

section And article In Browsers

Browsers generate an Accessibility Tree which you can inspect with the developer tools. You can open the developer tools, activate the Inspector, and navigate to the Accessibility tab.

Firefox, Chrome, and Microsoft Edge similarly present the respective roles of the article and section elements on the Accessibility Tree. The article element has the role of “article” on the accessibility tree. The section element has the role of the “section.” This means that the browsers accurately recognise what our grouping of content represents.

However, while the browsers correctly understand what our grouping of content represents, users do not get any particular hints about this. So articles and sections are not perceivable or otherwise navigable by the keyboard on the browser. If the page is styled, then visual cues provided by your design could hint at the grouping of content. But there is no default underlining or outline on focus as you’d get with links.

Note: I should briefly note that we (Manuel and I) got a little tripped up on browsers exposing the section element as having a role of “section” because, in aria accessibility definitions, the aria role of section is not the same as the HTML section element. The aria role of “section” is an abstract role and should not be used by authors/developers. So please do not set a role="section" attribute in your HTML. Anyway, it would seem that the browsers may be using their own internal accessibility terms. This conclusion is especially supported by the fact that in Firefox, for instance, images have the role of “graphic,” but aria does not have any role known as a graphic. Perhaps someone more knowledgeable would definitely be able to explain what is happening. However, the expected behavior is correct.

section And article In Screen Readers

Screen readers read the accessibility API and then handle the elements correctly. There are a couple of screen readers in use. Thankfully, AccessibilityOZ documents how sectioning elements are handled by screen readers, which still seems accurate at the time of writing this article.

article In Screen Readers

Where grouped content is wrapped in an article, different screen readers handle it differently.

In terms of being perceivable, AccessibilityOz documents that JAWS, Talkback on Android, and VoiceOver announce the entry into and exit from an “article” if it encounters it. NVDA and Narrator do not announce an article.

I specifically was able to test on NVDA and Narrator as I use a Windows laptop, and the article was not announced. Manuel was also kind enough to help test on VoiceOver and Talkback, and the article is announced if it is encountered as you traverse the page.

I snooped around and found that NVDA allows you to turn on the option to announce the presence of an article. It is just turned off by default. I am not certain how frequently non-developer users would customise that option.

Regarding navigation, users on Narrator cannot jump to an article as it is not perceivable. Users on NVDA that have activated the option to have articles announced cannot jump to an article. There is no shortcut for that. It is only announced if encountered while traversing the page. JAWS has a dedicated shortcut for moving through articles on a page by pressing the O key. VoiceOver users can jump across articles using the shortcut (VO + Shift + left/right arrow).

While some users would get the presence of an article announced, others would not. So, the experience is not uniform. I have also wondered if there is any practical use for announcing an article. I am not sure when I heard the announcement that I am “in the article” on a webpage, I would interpret it as “in an independent, redistributable and self-contained content.” It sounds more like I am in a “written body of work.” I do not have the capacity to test this anyway, so it really is just my own thought.

The question, then, is what direct benefits do users of my page get from grouping content semantically within an article? What does it translate to for my users after I have correctly wrapped my group in an article? If there is none, why should I not just use the div instead? Bruce Lawson’s article, “Why You Should Choose HTML5 article Over section” adequately covers that. Reader for Apple’s WatchOS looks out for article elements to appropriately determine what to display on the iWatch. While this is not a use case particularly prescribed by the web standards, perhaps we might see a trend of device makers taking this approach. So if you are designing your page with WatchOS in mind, this would be an additional reason to use article, at least over a div.

But I still wondered if there are any additional reasons directly for the benefit of users. Why would I want to jump through all articles on a webpage? Why jump through independent items on a webpage without context in the manner that JAWS and Voiceover allow? So I did some digging, and here is what I found about the prescribed functionality for article role by assistive technology:

An article may be nested to form a discussion where assistive technologies could pay attention to article nesting to assist the user in following the discussion…

…When nesting articles, the child articles represent content that is related to the content of the parent article. For instance, a weblog entry on a site that accepts user-submitted comments could represent the comments as articles nested within the article for the weblog entry.

…When the user navigates to an element assigned the role of article, assistive technologies that typically intercept standard keyboard events should switch to document browsing mode, as opposed to passing keyboard events through to the web application. Assistive technologies may provide a feature allowing the user to navigate the hierarchy of any nested article elements.

I was sadly unable to reproduce this behavior directly. Jumping through articles on VoiceOver with the shortcut merely announces “article, article, article.” It does not seem they implemented the feature to allow users to navigate the hierarchy of nested articles, or I could not get it to work.

However, it doesn’t hurt to build with nested articles if it is the appropriate thing to do. If screen reader makers implement this recommended behavior, your page is already prime and ready for it. Consider it some sort of future-proofing.

section In Screen Readers

Where grouped content is wrapped in a section, screen readers treat it more consistently.

In terms of being perceivable, all screen readers do not announce entry into or exit from a section. This also means in terms of navigation, there is no way to navigate from one section to another.

Extending section Into Navigable region

The imperceivable nature of section is only a default behavior. As such, we can customize our section and expose it to screen readers users using WAI-ARIA (Web Accessibility Initiative — Accessible Rich Internet Applications).

Here is a summary of what WAI-ARIA is and what it does culled from the MDN Docs:

WAI-ARIA (Web Accessibility Initiative — Accessible Rich Internet Applications) is a specification written by the W3C, defining a set of additional HTML attributes that can be applied to elements to provide additional semantics and improve accessibility wherever it is lacking...

Implying that while you may already be writing semantic HTML, you can customise and provide even greater semantic meaning!

In this specific case, we are more concerned with the category of landmark roles provided by ARIA, which are roles that provide navigational context for the application or the document. To understand better, the definition of landmark provided by WAI-ARIA reads:

A type of region on a page to which the user may want quick access. Content in such a region is different from that of other regions on the page and relevant to a specific user purpose, such as navigating, searching, perusing the primary content, etc.

With landmark roles, we can provide non-sighted users with a key experience that sighted (and fully non-disabled) users of our page would have: the ability to first scan or skim through a page and then decide where to focus their attention.

For the specific case of section and the intended semantic, we intend to pass to users; namely that the content in it is thematically related or has a central idea, the particular role of region is our concern.

As a landmark role, a region is intended by the w3c to be:

A perceivable section containing content that is relevant to a specific, author-specified purpose and sufficiently important that users will likely want to be able to navigate to the section easily and to have it listed in a summary of the page.

We can make specific sections of our page into regions calculated to make it easier for screen reader users to jump to that part of the page. This could be especially useful on pages populated with a lot of content other than the primary reason users might be on the page.

To create a region, there are two things to do. Firstly, make your element a region by including the attribute-value pairing role="region" in your element’s opening tag. Secondly, you give your region an accessible name. However, where your grouping element is a section, you only have to do the second. This is because if your section element has an accessible name, then it has an implicit role as a region. As such, it is not recommended to set a role that matches the implied semantics for the element. So let’s set an accessible name.

An accessible name is simply the name of a user interface element, especially as exposed by the accessibility API to assistive technologies.

The specification for the region role requires that:

Authors must give each element with a region role a brief label that describes the purpose of the content in the region.

An accessible name is required for the region role. If there is no accessible name, then browsers and assistive technologies must not expose a region to users because users will be jumping to a region with no description or context, almost like what happens with an article.

There are multiple ways to provide a name depending on the element involved. However, we shall narrow it down to what is relevant for a section being used as a region.

The first and most preferred way to name your region is to name via the aria-labelledby attribute. To do this, you reference a visible element on your page and direct the assistive technology to use the text content of that visible element as the name of the region. This visible element should preferably be a heading.

To do this, give the element whose content you are referencing an id attribute with a value of choice. Then give your section element an aria-labelledby attribute. Then set the value of the aria-labelledby attribute to the exact value as the id of the element whose content you are referencing. Take a look at this in action:

<section aria-labelledby="posts">
<!-- This area contains teasers for all blog posts on the website  -->
    <h2 id="posts">All blog posts</h2>
    <article>
        <header>
            <p>Cosima Mielke wrote</p>
                <h2>Expand Your Horizons (June 2022 Desktop Wallpapers Edition)</h2>
        </header>
        <div>
            <p>What could be a better way to welcome June than with some colorful inspiration? Well, we might have something for you: wallpapers created with love by artists and designers from across the globe.</p>
            <p><a>Continue reading ↬</a></p>
        </div>
</article>
    <!-- More blog post teasers here  -->
</section>

Take note that your aria-labelledby does not carry an #, unlike what obtains when linking to an id with an href. It is aria-labelledby="posts" not aria-labelledby="#posts". Remember also that we do not set a role=region for a section element. It is already implied once you give an accessible name.

Using this code example, screen readers would have the region announced to them under the landmark navigation as such “all blog posts, region” or something similar.

The second way to give an accessible name is to use the aria-label attribute if there is no visible element with content that could accurately label your region. In this case, the value you give to the aria-label itself would be read as the name of the region.

<section aria-label="all blog posts">
<!-- This area contains teasers for all blog posts on the website  -->
    <article>
        <header>
            <p>Cosima Mielke wrote</p>
                <h2>Expand Your Horizons (June 2022 Desktop Wallpapers Edition)</h2>
        </header>
        <div>
            <p>What could be a better way to welcome June than with some colorful inspiration? Well, we might have something for you: wallpapers created with love by artists and designers from across the globe.</p>
            <p><a>Continue reading ↬</a></p>
        </div>
</article>
    <!-- More blog post teasers here  -->
</section>

In this code example, there is no heading for the region that we can reference. So this region would be announced as “all blog posts, region” by directly reading the value we supplied for the aria-label attribute. You will notice that the accessible name is written in lowercase. This is because screenreaders could mistake words written in all caps to be acronyms and then spell them out alphabet by alphabet instead of reading them as a single word. The sentence case is fine, but please avoid all caps. If you want to make emphasis, use the em tag.

To recap, aria-labelledby is a referential naming mechanism and is recommended because users, relying on assistive technology, get labels from existing content on the page, ensuring that the experience they are served is significantly the same as what other users get. On the other hand, aria-label is a direct naming mechanism. Using it means that users relying on assistive technology get labels from the author’s interpretation of what the element does. This is why it is recommended to use it only where no visible content on the page itself is appropriate. Active decision-making is required.

Finally, not every section has to be a region. Seriously, on learning this new power to create a region, it is tempting to look at all elements on your page and go, “you get a region, you get a region, everyone gets a region.” Please do not do this. Why? Scott O’Hara explains, “Overpopulating a web page with landmarks will reduce their ability to help users find the most important parts of web pages.” Remember, regions should be attached to areas users want to reach easily. Now let us look at real-life examples of these in play.

Smashing Magazine uses the aria-label technique for the “Quick Summary” part of this blog post. If you open your developer tool and Inspect the “Quick Summary”, this is what the markup looks like:

<section aria-label="quick summary" class="article__summary">
    <span class="summary__heading">Quick summary ↬</span>
    <!--     Rest of summary continues here -->
</section>

Now screen reader users can jump to the “Quick Summary” region using shortcuts and get an overview of what the article is about without having to first interact with the whole article.

Let’s take another look at Twitter, a web application for using the aria-labelledby technique. Look at the developer tools, particularly the section holding your timeline. You will see an aria-labelledby="accessible-list-9" attribute in the section’s opening tag. It points to the h1 element just below it, which has an id="accessible-list-9" and text content that says “Your Home Timeline.” Now users of screen readers can use the landmark navigation menu in their screen reader and navigate to “Your Home Timeline region.”

Two questions may have crossed your mind. First, why is there a role="region" on the section element when the specs say that a section with an accessible name does not need to be assigned a region role expressly? Second, why can’t I see the h1 element with “Your Home Timeline” in my browser if the aria-labelledby is supposed to reference a visible element?

For the first question about declaring role="region" on the section element, the specs say it is not recommended to expressly set a role that is the same as the implied semantics. However, they do recognise that there might be browsers and devices that do correctly expose the implied semantics. As such, for an application like Twitter used by hundreds of millions of persons, it is reasonable to set the region role expressly to cover the bases as they cannot predict all the varying types of browsers and devices in use.

The second question is why the referenced element for the aria-labelledby is not on the page. This is a pattern/technique that people building pages with accessibility in mind employ every now and then. No rule has been broken here. An h1 element is a visible element. What has been done here is to use CSS to remove the visual rendering of elements that are not considered necessary for sighted users but crucial for non-sighted users. For sighted users, the timeline is identifiable without a heading. However, the heading is also a reference point to name the region for screen reader users, so we need it in our HTML. By using a neat CSS technique, one can take content off the screen but leave it visible to screen readers.

Here’s another interesting thing I noticed when you make your section into a region. Remember our Accessibility tab using the Inspector in our developer tools? Well, the section’s role on the accessibility tree does not directly change to region in Firefox. What happens is that a region branch is created as a child of the section. In Firefox, the tree becomes sectionregion.

However, in Chrome and Microsoft Edge, the section itself changes to a region role.

Should I Bother?

Yes, you absolutely should.

The truth is even if you are not designing for display on an iWatch or other smart gadgets, and even if you have no reason to create regions on your page, you should still use the correct element.

Firstly, this article by Mandy Michael reveals that browsers pay attention to your HTML structure to generate a Reader mode which strips the page of unnecessary information, images and background. Safari, Chrome, Firefox, Edge, and other reading apps specifically look out for HTML sectioning content to prioritise display for reading. The sectioning content includes article and section amongst others. Without carefully wrapping your content into appropriate elements, you risk it being ignored when a minimalist view is created.

Secondly, It helps you actively think about how you present your content. Content design is a crucial part of our page that we should be conscious about. It is the basis of our page. The words we use, the headings we use, and the length of our paragraphs all affect our users. How we group our content is also essential.

As designers and developers, we may feel that our main reason for grouping content is simply to style them. But if we start to care about the content, we may realise better ways to create our page. Grouping content does a lot more than preparing our content for visual styling. If we take care to write our HTML consciously, we can, to an extent, be certain that we have made our corner of the web a better place for all.

Writing this article and thinking about how I would have sectioned this page helped me create a coherent structure for my work. It helped me identify places where the content was out of place in terms of the surrounding context. With posts as long as this, thinking of how we group content becomes crucial.

Even where content is extremely short, thinking about how we group content helps create better content. In a recent knowledge-sharing webinar on Content Design and Accessibility, Amanda Diamond shared this slide showing how a very short content block can be broken up to make it easier for people to read. These two screenshots contain the exact same content, yet one is easier to digest. This would be a perfect place to use a section instead of just a div. Notice how each section carries an appropriate heading explaining each content block.

Conclusion

We have looked at a mental model that forces us to interact with our content to determine how best to group it. We question:

  • If the grouping plays a role in our document structure?
  • If it does, what role does it play?

From our answers, we can choose the appropriate grouping element for our content.

We have also looked at what happens when the browser builds an accessibility tree for our section or article elements and how to extend our section into a region to allow easy navigation.

Finally, I think we communicate with two sets of consumers of our content — the end-users who read our pages from an URL and others who have to interact with our markup. We may tend to think largely in terms of end-users when it comes to HTML. However, I believe writing HTML that is easy to understand and self-explanatory for whoever will work on it is sufficient reason to use the correct semantic element.

Dialog Components: Go Native HTML or Roll Your Own?

As the author of a library called AgnosticUI, I’m always on the lookout for new components. And recently, I decided to dig in and start work on a new dialog (aka modal) component. That’s something many devs like to have in their toolset and my goal was to make the best one possible, with an extra special focus on making it inclusive and accessible.

My first thought was that I would avoid any dependencies and bite the bullet to build my own dialog component. As you may know, there’s a new <dialog> element making the rounds and I figured using it as a starting point would be the right thing, especially in the inclusiveness and accessibilities departments.

But, after doing some research, I instead elected to leverage a11y-dialog by Kitty Giraudel. I even wrote adapters so it integrates smoothly with Vue 3, Svelte, and Angular. Kitty has long offered a React adapter as well.

Why did I go that route? Let me take you through my thought process.

First question: Should I even use the native <dialog> element?

The native <dialog> element is being actively improved and will likely be the way forward. But, it still has some issues at the moment that Kitty pointed out quite well:

  1. Clicking the backdrop overlay does not close the dialog by default
  2. The alertdialog ARIA role used for alerts simply does not work with the native <dialog> element. We’re supposed to use that role when a dialog requires a user’s response and shouldn’t be closed by clicking the backdrop, or by pressing ESC.
  3. The <dialog> element comes with a ::backdrop pseudo-element but it is only available when a dialog is programmatically opened with dialog.showModal().

And as Kitty also points out, there are general issues with the element’s default styles, like the fact they are left to the browser and will require JavaScript. So, it’s sort of not 100% HTML anyway.

Here’s a pen demonstrating these points:

Now, some of these issues may not affect you or whatever project you’re working on specifically, and you may even be able to work around things. If you still would like to utilize the native dialog you should see Adam Argyle’s wonderful post on building a dialog component with native dialog.

OK, let’s discuss what actually are the requirements for an accessible dialog component…

What I’m looking for

I know there are lots of ideas about what a dialog component should or should not do. But as far as what I was personally going after for AgnosticUI hinged on what I believe make for an accessible dialog experience:

  1. The dialog should close when clicking outside the dialog (on the backdrop) or when pressing the ESC key.
  2. It should trap focus to prevent tabbing out of the component with a keyboard.
  3. It should allow forwarding tabbing with TAB and backward tabbing with SHIFT+TAB.
  4. It should return focus back to the previously focused element when closed.
  5. It should correctly apply aria-* attributes and toggles.
  6. It should provide Portals (only if we’re using it within a JavaScript framework).
  7. It should support the alertdialog ARIA role for alert situations.
  8. It should prevent the underlying body from scrolling, if needed.
  9. It would be great if our implementation could avoid the common pitfalls that come with the native <dialog> element.
  10. It would ideally provide a way to apply custom styling while also taking the prefers-reduced-motion user preference query as a further accessibility measure.

I’m not the only one with a wish list. You might want to see Scott O’Hara’s article on the topic as well as Kitty’s full write-up on creating an accessible dialog from scratch for more in-depth coverage.

It should be clear right about now why I nixed the native <dialog> element from my component library. I believe in the work going into it, of course, but my current needs simply outweigh the costs of it. That’s why I went with Kitty’s a11y-dialog as my starting point.

Auditing <dialog> accessibility

Before trusting any particular dialog implementation, it’s worth making sure it fits the bill as far as your requirements go. With my requirements so heavily leaning on accessibility, that meant auditing a11y-dialog.

Accessibility audits are a profession of their own. And even if it’s not my everyday primary focus, I know there are some things that are worth doing, like:

This is quite a lot of work, as you might imagine (or know from experience). It’s tempting to take a path of less resistance and try automating things but, in a study conducted by Deque Systems, automated tooling can only catch about 57% of accessibility issues. There’s no substitute for good ol’ fashioned hard work.

The auditing environment

The dialog component can be tested in lots of places, including Storybook, CodePen, CodeSandbox, or whatever. For this particular test, though, I prefer instead to make a skeleton page and test locally. This way I’m preventing myself from having to validate the validators, so to speak. Having to use, say, a Storybook-specific add-on for a11y verification is fine if you’re already using Storybook on your own components, but it adds another layer of complexity when testing the accessibility of an external component.

A skeleton page can verify the dialog with manual checks, existing a11y tooling, and screen readers. If you’re following along, you’ll want to run this page via a local server. There are many ways to do that; one is to use a tool called serve, and npm even provides a nice one-liner npx serve <DIRECTORY> command to fire things up.

Let’s do an example audit together!

I’m obviously bullish on a11y-dialog here, so let’s put it to the test and verify it using some of the the recommended approaches we’ve covered.

Again, all I’m doing here is starting with an HTML. You can use the same one I am (complete with styles and scripts baked right in).

View full code
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>A11y Dialog Test</title>
    <style>
      .dialog-container {
        display: flex;
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        right: 0;
        z-index: 2;
      }
      
      .dialog-container[aria-hidden='true'] {
        display: none;
      }
      
      .dialog-overlay {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        right: 0;
        background-color: rgb(43 46 56 / 0.9);
        animation: fade-in 200ms both;
      }
      
      .dialog-content {
        background-color: rgb(255, 255, 255);
        margin: auto;
        z-index: 2;
        position: relative;
        animation: fade-in 400ms 200ms both, slide-up 400ms 200ms both;
        padding: 1em;
        max-width: 90%;
        width: 600px;
        border-radius: 2px;
      }
      
      @media screen and (min-width: 700px) {
        .dialog-content {
          padding: 2em;
        }
      }
      
      @keyframes fade-in {
        from {
          opacity: 0;
        }
      }
      
      @keyframes slide-up {
        from {
          transform: translateY(10%);
        }
      }

      /* Note, for brevity we haven't implemented prefers-reduced-motion */
      
      .dialog h1 {
        margin: 0;
        font-size: 1.25em;
      }
      
      .dialog-close {
        position: absolute;
        top: 0.5em;
        right: 0.5em;
        border: 0;
        padding: 0;
        background-color: transparent;
        font-weight: bold;
        font-size: 1.25em;
        width: 1.2em;
        height: 1.2em;
        text-align: center;
        cursor: pointer;
        transition: 0.15s;
      }
      
      @media screen and (min-width: 700px) {
        .dialog-close {
          top: 1em;
          right: 1em;
        }
      }
      
      * {
        box-sizing: border-box;
      }
      
      body {
        font: 125% / 1.5 -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif;
        padding: 2em 0;
      }
      
      h1 {
        font-size: 1.6em;
        line-height: 1.1;
        font-family: 'ESPI Slab', sans-serif;
        margin-bottom: 0;
      }
      
      main {
        max-width: 700px;
        margin: 0 auto;
        padding: 0 1em;
      }
    </style>
    <script defer src="https://cdn.jsdelivr.net/npm/a11y-dialog@7/dist/a11y-dialog.min.js"></script>
  </head>

  <body>
    <main>
      <div class="dialog-container" id="my-dialog" aria-hidden="true" aria-labelledby="my-dialog-title" role="dialog">
        <div class="dialog-overlay" data-a11y-dialog-hide></div>
        <div class="dialog-content" role="document">
          <button data-a11y-dialog-hide class="dialog-close" aria-label="Close this dialog window">
            ×
          </button>
          <a href="https://www.yahoo.com/" target="_blank">Rando Yahoo Link</a>
  
          <h1 id="my-dialog-title">My Title</h1>
          <p id="my-dialog-description">
            Some description of what's inside this dialog…
          </p>
        </div>
      </div>
      <button type="button" data-a11y-dialog-show="my-dialog">
        Open the dialog
      </button>
    </main>
    <script>
      // We need to ensure our deferred A11yDialog has
      // had a chance to do its thing ;-)
      window.addEventListener('DOMContentLoaded', (event) => {
        const dialogEl = document.getElementById('my-dialog')
        const dialog = new A11yDialog(dialogEl)
      });
    </script>
  </body>

</html>

I know, we’re ignoring a bunch of best practices (what, styles in the <head>?!) and combined all of the HTML, CSS, and JavaScript in one file. I won’t go into the details of the code as the focus here is testing for accessibility, but know that this test requires an internet connection as we are importing a11y-dialog from a CDN.

First, the manual checks

I served this one-pager locally and here are my manual check results:

FeatureResult
It should close when clicking outside the dialog (on the backdrop) or when pressing the ESC key.
It ought to trap focus to prevent tabbing out of the component with a keyboard.
It should allow forwarding tabbing with TAB and backward tabbing with SHIFT+TAB.
It should return focus back to the previously focused element when closed.
It should correctly apply aria-* attributes and toggles.
I verified this one “by eye” after inspecting the elements in the DevTools Elements panel.
It should provide Portals.Not applicable.
This is only useful when implementing the element with React, Svelte, Vue, etc. We’ve statically placed it on the page with aria-hidden for this test.
It should support for the alertdialog ARIA role for alert situations.
You’ll need to do two things:

First, remove data-a11y-dialog-hide from the overlay in the HTML so that it is <div class="dialog-overlay"></div>. Replace the dialog role with alertdialog so that it becomes:

<div class="dialog-container" id="my-dialog" aria-hidden="true" aria-labelledby="my-dialog-title" aria-describedby="my-dialog-description" role="alertdialog">

Now, clicking on the overlay outside of the dialog box does not close the dialog, as expected.
It should prevent the underlying body from scrolling, if needed.
I didn’t manually test but this, but it is clearly available per the documentation.
It should avoid the common pitfalls that come with the native <dialog> element.
This component does not rely on the native <dialog> which means we’re good here.

Next, let’s use some a11y tooling

I used Lighthouse to test the component both on a desktop computer and a mobile device, in two different scenarios where the dialog is open by default, and closed by default.

a11y-dialog Lighthouse testing, score 100.

I’ve found that sometimes the tooling doesn’t account for DOM elements that are dynamically shown or hidden DOM elements, so this test ensures I’m getting full coverage of both scenarios.

I also tested with IBM Equal Access Accessibility Checker. Generally, this tool will give you a red violation error if there’s anything egregious wrong. It will also ask you to manually review certain items. As seen here, there a couple of items for manual review, but no red violations.

a11y-dialog — tested with IBM Equal Access Accessibility Checker

Moving on to screen readers

Between my manual and tooling checks, I’m already feeling relatively confident that a11y-dialog is an accessible option for my dialog of choice. However, we ought to do our due diligence and consult a screen reader.

VoiceOver is the most convenient screen reader for me since I work on a Mac at the moment, but JAWS and NVDA are big names to look at as well. Like checking for UI consistency across browsers, it’s probably a good idea to test on more than one screen reader if you can.

VoiceOver caption over the a11y-modal example.

Here’s how I conducted the screen reader part of the audit with VoiceOver. Basically, I mapped out what actions needed testing and confirmed each one, like a script:

StepResult
The dialog component’s trigger button is announced.“Entering A11y Dialog Test, web content.”
The dialog should open when pressing CTRL+ALT +Space should show the dialog.“Dialog. Some description of what’s inside this dialog. You are currently on a dialog, inside of web content.”
The dialog should TAB to and put focus on the component’s Close button.“Close this dialog button. You are currently on a button, inside of web content.”
Tab to the link element and confirm it is announced.“Link, Rando Yahoo Link”
Pressing the SPACE key while focused on the Close button should close the dialog component and return to the last item in focus.

Testing with people

If you’re thinking we’re about to move on to testing with real people, I was unfortunately unable to find someone. If I had done this, though, I would have used a similar set of steps for them to run through while I observe, take notes, and ask a few questions about the general experience.

As you can see, a satisfactory audit involves a good deal of time and thought.

Fine, but I want to use a framework’s dialog component

That’s cool! Many frameworks have their own dialog component solution, so there’s lots to choose from. I don’t have some amazing spreadsheet audit of all the frameworks and libraries in the wild, and will spare you the work of evaluating them all.

Instead, here are some resources that might be good starting points and considerations for using a dialog component in some of the most widely used frameworks.

Disclaimer: I have not tested these personally. This is all stuff I found while researching.

Angular dialog options

In 2020, Deque published an article that audits Angular component libraries and the TL;DR was that Material (and its Angular/CDK library) and ngx-bootstrap both appear to provide decent dialog accessibility.

React dialog options

Reakit offers a dialog component that they claim is compliant with WAI-ARIA dialog guidelines, and chakra-ui appears to pay attention to its accessibility. Of course, Material is also available for React, so that’s worth a look as well. I’ve also heard good things about reach/dialog and Adobe’s @react-aria/dialog.

Vue dialog options

I’m a fan of Vuetensils, which is Austin Gil’s naked (aka headless) components library, which just so happens to have a dialog component. There’s also Vuetify, which is a popular Material implementation with a dialog of its own. I’ve also crossed paths with PrimeVue, but was surprised that its dialog component failed to return focus to the original element.

Svelte dialog options

You might want to look at svelte-headlessui. Material has a port in svelterial that is also worth a look. It seems that many current SvelteKit users prefer to build their own component sets as SvelteKit’s packaging idiom makes it super simple to do. If this is you, I would definitely recommend considering svelte-a11y-dialog as a convenient means to build custom dialogs, drawers, bottom sheets, etc.

I’ll also point out that my AgnosticUI library wraps the React, Vue, Svelte and Angular a11y-dialog adapter implementations we’ve been talking about earlier.

Bootstrap, of course

Bootstrap is still something many folks reach for, and unsurprisingly, it offers a dialog component. It requires you to follow some steps in order to make the modal accessible.

If you have other inclusive and accessible library-based dialog components that merit consideration, I’d love to know about them in the comments!

But I’m creating a custom design system

If you’re creating a design system or considering some other roll-your-own dialog approach, you can see just how many things need to be tested and taken into consideration… all for one component! It’s certainly doable to roll your own, of course, but I’d say it’s also extremely prone to error. You might ask yourself whether the effort is worthwhile when there are already battle-tested options to choose from.

I’ll simply leave you with something Scott O’Hara — co-editor of ARIA in HTML and HTML AAM specifications in addition to just being super helpful with all things accessibility — points out:

You could put in the effort to add in those extensions, or you could use a robust plugin like a11y-dialog and ensure that your dialogs will have a pretty consistent experience across all browsers.

Back to my objective…

I need that dialog to support React, Vue, Svelte, and Angular implementations.

I mentioned earlier that a11y-dialog already has ports for Vue and React. But the Vue port hasn’t yet been updated for Vue 3. Well, I was quite happy to spend the time I would have spent creating what likely would have been a buggy hand-rolled dialog component toward helping update the Vue port. I also added a Svelte port and one for Angular too. These are both very new and I would consider them experimental beta software at time of writing. Feedback welcome, of course!

It can support other components, too!

I think it’s worth pointing out that a dialog uses the same underlying concept for hiding and showing that can be used for a drawer (aka off-canvas) component. For example, if we borrow the CSS we used in our dialog accessibility audit and add a few additional classes, then a11y-dialog can be transformed into a working and effective drawer component:

.drawer-start { right: initial; }
.drawer-end { left: initial; }
.drawer-top { bottom: initial; }
.drawer-bottom { top: initial; }

.drawer-content {
  margin: initial;
  max-width: initial;
  width: 25rem;
  border-radius: initial;
}

.drawer-top .drawer-content,
.drawer-bottom .drawer-content {
  width: 100%;
}

These classes are used in an additive manner, essentially extending the base dialog component. This is exactly what I have started to do as I add my own drawer component to AgnosticUI. Saving time and reusing code FTW!

Wrapping up

Hopefully I’ve given you a good idea of the thinking process that goes into the making and maintenance of a component library. Could I have hand-rolled my own dialog component for the library? Absolutely! But I doubt it would have yielded better results than what a resource like Kitty’s a11y-dialog does, and the effort is daunting. There’s something cool about coming up with your own solution — and there may be good situations where you want to do that — but probably not at the cost of sacrificing something like accessibility.

Anyway, that’s how I arrived at my decision. I learned a lot about the native HTML <dialog> and its accessibility along the way, and I hope my journey gave you some of those nuggets too.


Dialog Components: Go Native HTML or Roll Your Own? originally published on CSS-Tricks. You should get the newsletter.

How to Test Your Website’s Accessibility With JAWS

When it comes to web apps and websites, the user experience is one of the key elements that helps in user acquisition and user retention. Though immense attention should be given to the design and development of new product features, a continuous watch should be kept on the overall user experience. An inaccessible website would give your customers — who use screen readers — an unpleasant and tiresome experience. 

How do you mitigate or completely solve this problem? By testing for accessibility issues. In this article, I outline ways to test the accessibility status of your website using the world’s foremost screen reader, JAWS (Job Access With Speech).

How to Conduct Accessibility Testing on Android Devices

As per recent research by the World Health Organization, roughly 15% of the worldwide population is ‘specially-abled’ in some form or another. Developers creating a mobile application for all need to keep this 15% in mind. Other than creating dedicated applications for differently-abled people, making sure the current applications are disabled-friendly is a moral responsibility for every developer to ensure all their users are able to access their application with ease.

To accelerate this process, innovative tools are used to check if the applications are functioning as per the Web Content Accessibility Guidelines or WCAG. This is where accessibility testing comes into the picture. Accessibility testing helps identify errors in software and functions incorporated in your systems and mobile phones to ensure that an application is accessible to people with disabilities, including visual, auditory, physical, speech, cognitive, language, learning, and neurological disabilities.

The Importance Of Manual Accessibility Testing

The Importance Of Manual Accessibility Testing

The Importance Of Manual Accessibility Testing

Eric Bailey

Earlier this year, a man drove his car into a lake after following directions from a smartphone app that helps drivers navigate by issuing turn-by-turn directions. Unfortunately, the app’s programming did not include instructions to avoid roads that turn into boat launches.

From the perspective of the app, it did exactly what it was programmed to do, i.e. to find the most optimal route from point A to point B given the information made available to it. From the perspective of the man, it failed him by not taking the real world into account.

The same principle applies for accessibility testing.

Designing For Accessibility And Inclusion

The more inclusive you are to the needs of your users, the more accessible your design is. Let’s take a closer look at the different lenses of accessibility through which you can refine your designs. Read article →

Automated Accessibility Testing

I am going to assume that you’re reading this article because you’re interested in learning how to test your websites and web apps to ensure they’re accessible. If you want to learn more about why accessibility is necessary, the topic has been covered extensively elsewhere.

Automated accessibility testing is a process where you use a series of scripts to test for the presence, or lack of certain conditions in code. These conditions are dictated by the Web Content Accessibility Guidelines (WCAG), a standard by the W3C that outlines how to make digital experiences accessible.

For example, an automated accessibility test might check to see if the tabindex attribute is present and if its value is greater than 0. The pseudocode would be something like:

A flowchart that asks if the tabindex value is present. If yes, it asks if the tabindex value is greater than 0. If it is greater than zero, it fails. If not, it passes. If no tabindex value is present, it also passes.

Failures can then be collected and used to generate reports that disclose the number, and severity of accessibility issues. Certain automated accessibility products can also integrate as a Continuous Integration or Continuous Deployment (CI/CD) tool, presenting just-in-time warnings to developers when they attempt to add code to a central repository.

These automated programs are incredible resources. Modern websites and web apps are complicated things that involve hundreds of states, thousands of lines of code, and complicated multi-screen interactions. It’d be absurd to expect a human (or a team of humans) to mind all the code controlling every possible permutation of the site, to say nothing of things like regressions, software rot, and A/B tests.

Automation really shines here. It can repeatedly and tirelessly pour over these details with perfect memory, at a rate far faster than any human is capable of.

However…

Automated accessibility tests aren’t a turnkey solution, nor are they a silver bullet. There are some limitations to keep in mind when using them.

Thinking To Think Of Things

One of both the best and worst aspects of the web is that there are many different ways to implement a solution to a problem. While this flexibility has kept the web robust and adaptable and ensured it outlived other competing technologies, it also means that you’ll sometimes see code that is, um, creatively implemented.

The test suite is only as good as what its author thought to check for. A naïve developer might only write tests for the happy path, where everyone writes semantic HTML, fault-tolerant JavaScript, and well-scoped CSS. However, this is the real world. We need to acknowledge that things like tight deadlines, unfamiliarity with the programming language, atypical user input, and sketchy 3rd party scripts exist.

For example, the automated accessibility testing site Tenon.io wisely includes a rule that checks to see if a form element has both a label element and an aria-label associated with it, and if the text strings for both declarations differ. If they do, it will flag it as an issue, as the visible label may be different than what someone would hear if they were navigating using a screen reader.

If you’re not using a testing service that includes this rule, it won’t be reported. The code will still “pass”, but it’s passing by omission, not because it’s actually accessible.

State

Some automated accessibility tests cannot parse the various states of interactive content. Critical parts of the user interface are effectively invisible to automation unless the test is run when the content is in an active, selected, or disabled state.

By interactive content, I mean things that the user has yet to take action on, or aren’t present when the page loads. Unopened modals, collapsed accordions, hidden tab content and carousel slides are all examples.

It takes sophisticated software to automatically test the various states of every component within a single screen, let alone across an entire web app or website. While it is possible to augment testing software with automated accessibility checks, it is very resource-intensive, usually requiring a dedicated team of engineers to set up and maintain.

“Valid” Markup

Accessible Rich Internet Applications (ARIA) is a set of attributes that extend HTML to allow it to describe interaction in a way that can be better understood by assistive technologies. For example, the aria-expanded attribute can be toggled by JavaScript to programmatically communicate if a component is in an expanded (true) or collapsed (false) state. This is superior to toggling a CSS class like .is-expanded, where the update in state is only communicated visually.

Just having the presence of ARIA does not guarantee that it will automatically make something accessible. Unfortunately, and in spite of its first rule of use, ARIA is commonly misunderstood, and consequently abused. A lot of off-the-shelf code has this problem, perpetuating the issue.

For example, certain ARIA attributes and values can only be applied to certain elements. If incorrectly applied, assistive technology will ignore or misreport the declaration. Certain roles, known as Abstract Roles, only exist to set up the overall taxonomy and should never be placed in markup.

<button role="command">Save</button>

<!-- Never do this -->

To further complicate the issue, support for ARIA is varied across browsers. While an attribute may be used appropriately, the browser may not communicate the declared role, property, or state to assistive technology.

There is also the scenario where ARIA can be applied to an element and be valid from a technical standpoint, yet be unusable from an assistive technology perspective. For example:

<h1 aria-hidden=“true”>
  Tired of unevenly cooked asparagus? Try this tip from the world’s oldest cookbook.
</h1>

This one Weird Trick.

The aria-hidden declaration will remove the presence of content from assistive technology, yet allow it to be still rendered visibly on the page. It’s a problematic pattern.

Headings — especially first-level headings — are vital in communicating the purpose of a page. If a person is using assistive technology to navigate, the aria-hidden declaration applied to the h1 element will make it difficult for them to quickly determine the page’s purpose. It will force them to navigate around the rest of the page to gain context, an annoying and labor-intensive process.

Some automated accessibility tests may scan the code and not report an error since the syntax itself is valid. The automation has no way of knowing the greater context of the declaration’s use.

This isn’t to say you should completely avoid using ARIA! When authored with care and deliberation, ARIA can fix the gaps in accessibility that sometimes plague complicated interactions; it provides some much-needed context to the people who rely on assistive technology.

Much-Needed Context

As the soggy car demonstrates, computers are awful at understanding the overall situation of the outside world. It’s up to us humans to be the ultimate arbiters in determining if what the computer spits out is useful or not.

Debunking

Before we discuss how to provide appropriate context, there are a few common misunderstandings about accessibility work that need to be addressed:

First, not all screen reader users are blind. In addition to all the points Adrian Roselli outlines in his post, some food for thought: the use of voice assistants is on the rise. When’s the last time you spoke to Siri or Alexa?

Second, accessibility is more than just screen readers. The rules outlined in the Web Content Accessibility Guidelines ensure that the largest number of people can read and operate technology, regardless of ability or circumstance.

For example, the rule that stipulates a website or web app needs to be able to work regardless of device orientation benefits everyone. Some people may need to mount their device in a fixed location in a specific orientation, such as in landscape mode on the arm of a wheelchair. Others might want to lie in bed and watch a movie, or better investigate a product photo (pinch and pull zooming will also be helpful to have here).

Third, disabilities can be conditional and can be brought about by your environment. It can be a short-term thing, like rain on your glasses, sleep deprivation, or an allergies-induced migraine. It can also be longer-term, such as a debilitating illness, broken limb, or a depressive episode. Multiple, compounding conditions can (and do) affect individuals.

That all being said, many accessibility fixes that help screen readers work properly also benefit other assistive technologies.

Get Your Feet Wet

Knowing where to begin can be overwhelming. Consider Michiel Bijl’s great advice:

“Before you release a website, tab through it. If you cannot see where you are on the page after each tab; you're not finished yet. #a11y

Tab through a few of the main user flows on your website or web app to determine if all interactive components’ focus states are visually apparent, and if they can be activated via keyboard input. If there’s something you can click or tap on that isn’t getting highlighted when receiving keyboard focus, take note of it. Also pay attention to the order interactive components are highlighted when focused — it should match the reading order of the site.

An obvious focus state and logical tab order go a great way to helping make your site accessible. These two features benefit a wide variety of assistive technology, including, but not limited to, screen readers.

If you need a baseline to compare your testing to, Dave Rupert has an excellent project called A11Y Nutrition Cards, which outlines expected behavior for common interactive components. In addition, Scott O’Hara maintains a project called a11y Styled Form Controls. This project provides examples of components such as switches, checkboxes, and radio buttons that have well-tested and documented support for assistive technology. A clever reader might use one of these resources to help them try out the other!

A screenshot of homepage for the a11y Styled Form Controls website placed over a screenshot of the Nutrition Cards for Accessible Components website.
(Large preview)

The Fourth Myth

With that out of the way, I’m going to share a fourth myth with you: not every assistive technology user is a power user. Like with any other piece of software, there’s a learning curve involved.

In her post about Aaptiv’s redesign, Lisa Zhu discovers that their initial accessibility fix wasn’t intuitive. While their first implementation was “technically” correct, it didn’t line up with how people who rely on VoiceOver actually use their devices. A second solution simplified the interaction to better align with their expectations.

Don’t assume that just because something hypothetically functions that it’s actually usable. Trust your gut: if it feels especially awkward, cumbersome, or tedious to operate for you, chances are it’ll be for others.

Dive Right In

While not every accessibility issue is a screen reader issue, you should still get in the habit of testing your site with one. Not an emulator, simulator, or some other proxy solution.

If you find yourself struggling to operate a complicated interactive component using basic screen reader commands, it’s probably a sign that the component needs to be simplified. Chances are that the simplification will help non-assistive technology users as well. Good design benefits everyone!

The same goes for navigation. If it’s difficult to move around the website or web app, it’s probably a sign that you need to update your heading structure and landmark roles. Both of these features are used by assistive technology to quickly and efficiently navigate.

Two code examples for a sidebar. One uses a div element, while the others uses an aside element. Both have the class of sidebar applied to them, with a subheading of Recent Posts.
Both of these are sidebars, but only one of them is semantically described as such. A computer doesn't know what a sidebar is, so it's up to you to tell it.

Another good thing to review is the text content used to describe your links. Hopping from link to link is another common assistive technology navigation technique; some screen readers can even generate a list of all link content on the page:

“Think before you link! Your "helpful" click here links look like this to a screen reader user. ALT = JAWS links list”
Tweet by Neil Milliken


Neil Milliken

When navigating using an ordered list devoid of the surrounding non-link content, avoiding ambiguous terms like “click here” or “more info” can go a long way to ensuring a person can understand the overall meaning of the page. As a bonus, it’ll help alleviate cognitive concerns for everyone, as you are more accurately explaining what a user should expect after activating a link.

How To Test

Each screen reader has a different approach to how it announces content. This is intentional. It’s a balancing act between the product’s features, the operating system it is installed on, the form factor it is available in, and the types of input it can receive.

The Browser Wars taught us the folly of developing for only one browser. Similarly, we should not cater to a single screen reader. It is important to note that many people rely exclusively on a specific screen reader and browser combination — by circumstance, preference, or necessity’making this all the more important. However, there is a caveat: each screen reader works better when used with a specific browser, typically the one that allows it access to the greatest amount of accessibility API information.

All of these screen readers can be used for free, provided you have the hardware. You can also virtualize that hardware, either for free or on the cheap.

Automate

Automated accessibility tests should be your first line of defense. They will help you catch a great deal of nitpicky, easily-preventable errors before they get committed. Repeated errors may also signal problems in template logic, where one upstream tweak can fix multiple pages. Identifying and resolving these issues allows you to spend your valuable manual testing time much more wisely.

It may also be helpful to log accessibility issues in a place where people can collaborate, such as Google Sheets. Quantifying the frequency and severity of errors can lead to good things like updated documentation, opportunities for lunch and learn education, and other healthy changes to organizational workflow.

Much like manual testing with a variety of screen readers, it is recommended that you use a combination of automated tools to prevent gaps.

Windows

The two most popular screen readers on Windows are JAWS and NVDA.

JAWS

JAWS (Job Access With Speech) is the most popular and feature-rich screen reader on the market. It works best with Firefox and Chrome, with concessions for supporting Internet Explorer. Although it is pay software, it can be operated in full in demo mode for 40 minutes at a time (this should be more than sufficient to perform basic testing).

NVDA

NVDA (NonVisual Desktop Access) is free, although a donation is strongly encouraged. It is a feature-rich alternative to JAWS. It works best with Firefox.

Narrator

Windows comes bundled with a built-in screen reader called Narrator. It works well with Edge, but has difficulty interfacing with other browsers.

Apple

macOS

VoiceOver is a powerful screen reader that comes bundled with macOS. Use it in conjunction with Safari, first making sure that full keyboard access is enabled.

iOS

VoiceOver is also included in iOS, and is the most popular mobile screen reader. Much like its desktop counterpart, it works best with Safari. An interesting note here is that according to the 2017 WebAIM screen reader survey, a not-insignificant amount of respondents augment their phone with external hardware keyboards.

Android

Google recently folded TalkBack, their mobile screen reader, into a larger collection of accessibility services called the Android Accessibility Suite. It works best with Mobile Chrome. While many Android apps are notoriously inaccessible, it is still worth testing on this platform. Android’s growing presence in emerging markets, as well as increasing internet use amongst elderly and lower-income demographics, should give pause for consideration.

Popular screen readers
Screen Reader Platform Preferred Browser(s) Manual Launch Quit
JAWS Windows Chrome, Firefox JAWS 2018 Documentation Launch JAWS as you would any other Windows application Insert + F4
NVDA Windows Firefox NVDA 2018.2.1 User Guide Ctrl + Alt + N Insert + Q
Narrator Windows Edge Get started with Narrator Windows key + Control + Enter Windows key + Control + Enter
VoiceOver macOS Safari VoiceOver Getting Started Guide Command + F5 or tap the Touch ID button 3 times Command + F5 or tap the Touch ID button 3 times
Mobile VoiceOver iOS Mobile Safari VoiceOver overview - iPhone User Guide Tell Siri to, “Turn on VoiceOver.” or activate in Settings Tell Siri to, “Turn off VoiceOver.” or deactivate in Settings
Android Accessibility Suite Android Mobile Chrome Get started on Android with TalkBack Press both volume keys for 3 seconds Press both volume keys for 3 seconds

Call The Professionals

If you do not require the use of assistive technology on a frequent basis then you do not fully understand how the people who do interact with the web.

Much like traditional user testing, being too close to the thing you created may cloud your judgment. Empathy exercises are a good way to become aware of the problem space, but you should not use yourself as a litmus test for whether the entire experience is truly accessible. You are not the expert.

If your product serves a huge population of users, if its core base of users trends towards having a higher probability of disability conditions (specialized product, elderly populations, foreign language speakers, etc.), and/or if it is required to be compliant by law, I would strongly encourage allocating a portion of your budget for testing by people with disabilities.

“At what point does your organisation stop supporting a browser in terms of % usage? 18% of the global pop. have an #Accessibility requirement, 2% people have a colour vision deficient. But you consider 2% IE usage support more important? Support everyone be inclusive.”

Mark Wilcock

This isn’t to say you should completely delegate the responsibility to these testers. Much as how automated accessibility testing can detect smaller issues to remove, a first round of basic manual testing helps professional testers focus their efforts on the complicated interactions you need an expert’s opinion on. In addition to optimizing the value of their time, it helps to get you more comfortable triaging. It is also a professional courtesy, plain and simple.

There are a few companies that perform manual testing by people with disabilities:

Designed Experiences

We also need to acknowledge the other large barrier to accessible sites that can’t be automated away: poor user experience.

User experience can make or break a product. Your code can compile perfectly, your time to first paint can be lightning quick, and your Webpack setup can be beyond reproach. All this is irrelevant if the end result is unusable. User experience encompasses all users, including those who navigate with the aid of assistive technology.

If a person cannot operate your website or web app, they’ll abandon it and not think twice. If they are forced to use your site to get a service unavailable by other means, there’s a growing precedent for taking legal action (and rightly so).

As a discipline, user experience can be roughly divided into two parts: how something looks and how it behaves They’re intrinsically interlinked concepts — work on either may affect both. While accessible design is a topic unto itself, there are some big-picture things we can keep in mind when approaching accessible user experiences from a testing perspective:

How It Looks

The WCAG does a great job covering a lot of the basics of good design. Color contrast, font size, user-facing state: a lot of these things can be targeted by automation. What you should pay attention to is all the atomic, difficult to quantify bits that compound to create your designs. Things like the words you choose, the fonts you use to display them, the spacing between things, affordances for interaction, the way you handle your breakpoints, etc.

“A good font should tell you:
the difference between m and rn
the difference between I and l
the difference between O and 0.”

mallory, alice & bob

It’s one of those “an ounce of prevention is worth a pound of cure” situations. Smart, accessible defaults can save countless time and money down the line. Lean and mean startups all the way up to multinational conglomerates value efficient use of resources, and this is one of those places where you can really capitalize on that. Put your basic design patterns — say collected in something like a mood board or living style guide — in front of people early and often to see if your designed intent is clear.

How It Behaves

An enticing color palette and collection of thoughtfully-curated stock photography only go so far. Eventually, you’re going to have to synthesize all your design decisions to create something that addresses a need.

Behavior can be as small as a microinteraction, or as large as finding a product and purchasing it. What’s important here is to make sure that all the barriers to a person trying to accomplish the task at hand are removed.

If you’re using personas, don’t create a separate persona for a user with a disability. Instead, blend accessibility considerations into your existing ones. As a persona is an abstracted representation of the types of users you want to cater to, you want to make sure the kinds of conditions they may be experiencing are included. Disability conditions aren’t limited to just physical impairments, either. Things like a metered data plan, non-native language, or anxiety are all worth integrating.

“When looking at your site's analytics, remember that if you don't see many users on lower end phones or from more remote areas, it's not because they aren't a target for your product or service. It is because your mobile experience sucks.
As a developer, it's your job to fix it.”

Estelle Weyl

User testing, ideally simulating conditions as close to what a person would be doing in the real world (including their individual device preferences and presence of assistive technology), is also key. Verifying that people are actually able to make the logical leaps necessary to operate your interface addresses a lot of cognitive concerns, a difficult-to-quantify yet vital thing to accommodate.

We Shape Our Tools, Our Tools Shape Us

Our tool use corresponds to the kind of work we do: Carpenters drive nails with hammers, chefs cook using skillets, surgeons cut with scalpels. It’s a self-reinforcing phenomenon, and it tends to lead to over-categorization.

Sometimes this over-categorization gets in the way of us remembering to consider the real world. A surgeon might have a carpentry hobby; a chef might be a retired veterinarian. It’s important to understand that accessibility is everyone’s responsibility, and there are many paths to making our websites and web apps the best they can be for everyone. To paraphrase Mikey Ilagan, accessibility is a holistic practice, essential to some but useful to all.

Used with discretion, ARIA is a very good tool to have at our disposal. We shouldn’t shy away from using it, provided we understand the how and why behind why they work.

The same goes for automated accessibility tests, as well as GPS apps. They’re great tools to have, just get to know the terrain a little bit first.

Resources

Automated Accessibility Tools

Professional Services

References

Quick Tests

Further Reading

Smashing Editorial (rb, ra, yk, il)