✨ Inclusive components: making modals accessible 🧑‍🦯

Alena Nik - Jan 19 '21 - - Dev Community

In order for us to help create a more accessible, equal society for everyone, change needs to happen. But for those changes to happen, we need to have conversations.
Holly - Award-winning disability blogger and writer

Introduction

As Holly is saying, 2021 seems like a good year to start having a conversation about accessibility, if you haven't started yet.

Working from home, shopping online, ordering food, doing anything online is often a challenge for someone who is blind or visually impaired and relies on a screen reader.

What we can do as front-end developers?
Make a small change, educate ourselves, have conversations, not to be afraid of sharing information.

I've started my accessibility journey this year and I invite you to join me. Today I'm sharing my notes on modals.

Definition

A modal dialog is a dialog that appears on top of the main content and moves the system into a special mode requiring user interaction.
This dialog disables the main content until the user explicitly interacts with the modal dialog.

Should I avoid modals all together? 🤨

Modals are evil and should be avoided it's a common misconception that existed for some time. The reasons might be:

  • Modals eat up a lot of space
  • If the content doesn't fit inside, the scrollbars might cause a problem on mobile screens
  • Any other reason
  • Often unaccessible

You can definitely discuss all of them with your designer, but let's break down the last one together.

Often, modals are a piece of UI that contains text or an image, or a form and buttons. Like alerts, modals disrupt the flow of what the user is doing, so we must help them to be able to open it, close and read through the content with the screen reader.

The problem

If the user navigates with the keyboard through our website, and the modal pops up, the user can't interact with the content (sign-in, say yes or even close it) because the keyboard focus is behind the modal. Pressing TAB or ESC won't work either. Very frustrating. 😣 If the user can't navigate, they will need sighted assistance.

What do the specs say? 🤓

First of all, "the rules" or "read the specs" sounds intimidating, I get that. No, really. But bear with me:

WCAG stands for Web Content Accessibility Guidelines. It's useful to developers as a guideline to make websites more accessible for disabled people. Those standards exist for us to use them, as any other resource.
Personally, I find myself reaching out to "Quick Reference":
A customizable quick reference to Web Content Accessibility Guidelines (WCAG) 2 requirements

This is what it says about Modal Dialog:

  • Initial focus placement.
  • Authors SHOULD provide a dialog label, which can be done with the aria-label or aria-labelledby attribute.

  • Keyboard interaction

➡️ Tab 
Moves focus to next focusable element inside the dialog.
When focus is on the last focusable element in the dialog, moves focus to the first focusable element in the dialog.
➡️ Shift + Tab 
Moves focus to previous focusable element inside the dialog.
When focus is on the first focusable element in the dialog, moves focus to the last focusable element in the dialog.
↩️ Escape   
Closes the dialog.
Enter fullscreen mode Exit fullscreen mode
  • Focus and accessible descriptions are set based on the content of each dialog, usage of aria-describedby

  • When closed ❎, the focus is set on another element that provides logical work flow.

What Can I do? 🙂

There are many edge cases and it all depends on your particular modal dialog, but here are some quick-wins:

  • HTML
<main>
  ...content of my page...
  <button onClick="openDialog">Sign in</button>
</main>
<div role="dialog" 
     id="dialog"
     aria-modal="true"
     aria-labelledby="modalTitle"
     aria-describedby="modalDescription"
     tabindex="-1"
>    
  <h1 id='modalTitle'>Registration Form</h1>
  <button onClick="closeDialog">Close me</button>
</div>
Enter fullscreen mode Exit fullscreen mode
  • Labeling

Give the modal an ARIA aria-describedby attribute which will be linked to the id of some visually hidden text which describes the modal’s function, and how to exit it.

The dialog has either:
A value set for the aria-labelledby property that refers to a visible dialog title.
A label specified by aria-label.
Optionally, the aria-describedby property is set on the element with the dialog role to indicate which element or elements in the dialog contain content that describes the primary purpose or message of the dialog.
WAI-ARIA Roles, States, and Properties

  • Shift focus when the modal is open

If the content is large enough that focusing on the first interactive element could cause the beginning of content to scroll out of view, it is advisable to add tabindex=-1.

Upon clicking the modal-activating button, all the main content should get an aria-hidden='true' attribute so that a screen reader will no longer read any of the content. Additionally, the modal should get an aria-hidden='false' and go from having {display: none;} to {display: block;}.

When a user clicks the ‘Open modal’ button then, we need to actively set their focus to the modal with JavaScript, and if they ever tab outside the modal, we need to set the focus back on the modal.

Tip: one of the tools that I use the most for focus debugging

✨ What has focus?
https://codepen.io/svinkle/pen/WgYRxq

  • When the dialog is open, pressing the ESC key should close it

  • What if the button is X?

It is strongly recommended that the tab sequence of all dialogs include a visible element with role button that closes the dialog, such as a close icon or cancel button.

If the 'close' element is implemented as a button containing merely the letter 'x', you can do the following:

<div id="dialog">
   <button>Close</button>               
</div>
Enter fullscreen mode Exit fullscreen mode

Exactly, just use the word "close". 'x' is commonly known multiplication sign, we don't want to confuse our users.

If you can't avoid it this is also another accessible option:

<button>
  <span aria-hidden="true">X</span>
  <span class="visually-hidden>Close</span>
</button>
Enter fullscreen mode Exit fullscreen mode

In case of the icon, you need to make sure to use the high contrast close icon in the top corner for people people who have low vision:

<button​​ id=​"​open-toggle" a​ria-expanded​="​false"​​ aria-controls​=​"menu"><svg aria-hidden="true" focusable="false">...</svg><span ​​class=​"visually-hidden">​Close<​/span></button>
Enter fullscreen mode Exit fullscreen mode

“Hide” the svg with aria-hidden="true" focusable="false
icon itself (an svg image) should become irrelevant to screen reader with aria-hidden.

The svg also should have a focusable attribute set to false which prevents the icon itself from receiving focus in IE.

If a real <button> is not used, then your <div> will need:

  • tabindex="0" (to allow keyboard focus to move to it)
  • a click handler (for mouse users)
  • a keyboard handler (for keyboard users to use space and enter to select it)
  • a role="button" so a screen reader announces the proper semantics.

💁🏼‍♀️ To recap:

If we are dealing with a modal:

  • We want to manage the focus for full-sized modal so it’s not trapped behind.
  • Modal needs labeling role="dialog" aria-modal="true" to the modal window.
  • Ideally, close button would work with esc key.
  • We want to be able to close it and interact with the content.

Resources 📂

Github 👩🏼‍💻

GitHub logo andrewvasilchuk / vue-accessible-modal

Vue.js component for accessible modals



Chakra UI is one of my favorite references for accessibility in Vue components. They are doing an amazing job!

GitHub logo chakra-ui / chakra-ui-vue

⚡️ Build scalable and accessible Vue.js applications with ease.

Articles 📋

Creating An Accessible Modal Dialog
Modals (Dialog Windows)
Notifications

Specs 🧷

3.9 Dialog (Modal)

Conclusion 💡

Building accessible websites shows that you care about disabled people. It's a small change that makes difference.

How often could you hear someone say "I'm not sacrificing visuals for accessibility"? The good news is you don't have to. 😊 What we can do is make sure that all of our users can have similar experiences: to be able to find a button, have a dialog with the interface, close a modal or add items to the card.

I'm quoting Holly again and wish you good luck in making a small change for a better experience for all. Just give it a try tomorrow.

"The lack of accessibility leaves disabled people feeling frustrated, isolated, and forgotten. But when accessibility is considered, disabled people feel included and most importantly, we feel equal.

Accessibility should be at the heart ❤️ of everything you do. Whether it personally makes a difference to your life or not, accessibility should always be considered and made a priority."

If you like this article and the information that I have put together, please, share it with your colleague and reach out to me on Twitter, whether you liked it or have suggestions 💚

. . . . .