Dialogs 1/2

Introduction

Dialogs are part of the core UI components on a website. Unfortunately, there is no native HTML component to create this kind of object. These dialogs must be created from scratch during development. It often adds accessibility issues if we do not pay attention.

Difficulties associated with dialogs are most of the time impossible to overcome, specifically for those navigating with the keyboard (Tab), or using a screen reader (visually impaired or blind). This example will show you step-by-step how to create an accessible dialog.

Usability reminder: avoid using dialogs, windows and other modal popups, especially for displaying information, their usability and readability are issues for all users. Only use them with few information and particularly to confirm actions (validating an action, confirming erasing data…).

If you do not want to create the component from scratch, you can also use the “modal” component of the Boosted library which has the double advantage of being accessible and being already branded with the Orange colours.

Final example

Here is the final rendering of the dialog, we will show you how to create it step-by-step.

Step 1: defining the layout

Here we create the design of our dialog with a <div> tag. We add:

Warning

I am a modal dialog. I am accessible to mouse, keyboard and screen reader users.


      <div class="dialog">
        <div class="dialogContainer">
          <button>X</button>
          <h1>Warning</h1>
          <p>I am a modal dialog. I am accessible to mouse, keyboard and screen reader users.</p>
          <button>OK</button>
          <button>Cancel</button>
        </div>
      </div>
      

Testing

Step 2: handling keyboard navigation

To navigate properly with the keyboard:

In this new example, we save the location of the focus at the opening:


       // Save the focus position that will be used when closing
       $('#step2-dialog').attr('data-focusBack', 'step2-openButton');

       // Set the focus on the default item
       $('#step2-dialog .defaultFocus').focus();
      

It resets the focus when closing:


        // Resets the focus when closing the dialog
        $('#'+$('#step2-dialog').attr('data-focusBack')).focus();
      

We also have to prevent the focus from going out of the dialog. When the focus is set on the last element it should go back to the first element and vice versa. There are several solutions to create this behaviour. In this example, two empty span tags are added at the beginning and at the end of the dialog. These are made ​​focusable using the tabindex="0" attribute. When the first span tag receives the focus, it is moved to the last element of the dialog. When the last span receives the focus, it is moved to the first element of the dialog.

Empty span tags have the advantage of not being vocalized by screen readers.


       $('.dialog-start').on('focus', function () {
          $(this).parent().find('button:last').focus();
       });

       $('.dialog-stop').on('focus', function () {
          $(this).parent().find('button:first').focus();
       });
      

Warning

I am a modal dialog. I am accessible to mouse, keyboard and screen reader users.

Finally, we listen to the onKeyPress event to close the dialog when the Escape key is pressed.
Here is the updated HTML code for the dialog:

      <div id="step2-dialog" class="dialog">
        <span tabindex="0" class="dialog-start"></span>
        <div class="dialogContainer">
          <button>X</button>
          <h1>Warning</h1>
          <p>I am a modal dialog. I am accessible to mouse, keyboard and screen reader users.</p>
          <button class="defaultFocus">OK</button>
          <button>Cancel</button>
        </div>
        <span tabindex="0" class="dialog-stop"></span>
      </div>
      

Testing

Step 3: handling screen reader navigation

To navigate properly with a screen reader:

The aria-labelledby attribute is used to specify the id of the element containing the title of the dialog. This will be spoken automatically by the screen reader. The aria-describedby attribute is used to specify the id of the element containing the description. This description will automatically be vocalized after the title of the dialog. Finally, the aria-label attribute on the close button (“X”) specifies a label to be vocalized (otherwise “X” will be read).


      <div id="final-dialog" role="dialog" aria-labelledby="final-dialogTitle" aria-describedby="final-description">
        <span tabindex="0" class="dialog-start"></span>
        <div class="dialogContainer">
          <button aria-label="close" title="Close">X</button>
          <h1 id="final-dialogTitle">Warning</h1>
          <p id="final-description">I am a modal dialog. I am accessible to mouse, keyboard and screen reader users.</p>
          <button class="defaultFocus">OK</button>
          <button>Cancel</button>
        </div>
        <span tabindex="0" class="dialog-stop"></span>
      </div>
      

Testing

Note on navigating using a screen reader

In a web page, when navigating with a screen reader the user mainly uses the Up arrow and the Down arrow. This navigation mode is called “document mode”. One can also use the Tab key but in this case only focusable elements will be vocalized.

In native applications, navigation is mainly using the Tab key. This navigation mode is called “application mode.” Using the ARIA dialog role, the screen reader goes into the “application mode”, i.e. the navigation with the mouse is no longer available when a dialog is displayed. In this case you must use the Tab key to navigate between the buttons of the dialog.

Note that it is also possible to force the use of the “application” or “document” mode with the attribute role, however users are not used to these navigation mode changes and it is currently not recommended to do it, except in exceptional cases:


      <div role="application">…</div>
      <div role="document">…</div>