Make a screen reader talk with JavaScript and ARIA

Associated themes :

Preamble

In some cases, it may be interesting to want to make a screen reader talk, to confirm an action for instance. In this example, we will see how this can be achieved simply through the use of the aria-live attribute.

Working principle

The aria-live attribute positioned on an element makes it possible to notify a screen reader that the element must be vocalized automatically when its content is modified. The possible values are:

  • aria-live="off": default value, the user is not told when the element is updated.
  • aria-live="polite": the screen reader vocalises in a polite manner when the element is updated. This means that if the screen reader was already reading text, it will not be interrupted.
  • aria-live="assertive": the screen reader is interrupted in its reading and tells the user about the update straight away.

And in Javascript?

In many cases this first solution helps making an application accessible. There are however some cases when it would be convenient to have the screen reader talk directly through the use of a Javascript function (i.e.: speak('Article removed from basket')). Unfortunately this is not possible natively.

Luckily we can write a small Javascript function that will use an aria-live element under the hood to achieve this.

When the speak function is called, we add a div at the end of the page. We add an aria-live attribute to it and we insert the message to vocalise to the div. To prevent the message from being visible in the page, we can also add a hiding class to this div, so that it will be vocalized but won’t be seen on screen.

Code detail


  /* srSpeak(text, priority)
    text: the message to be vocalised
    priority (non mandatory): "polite" (by default) or "assertive" */

  function srSpeak(text, priority) {
      var el = document.createElement("div");
      var id = "speak-" + Date.now();
      el.setAttribute("id", id);
      el.setAttribute("aria-live", priority || "polite");
      el.classList.add("visually-hidden");
      document.body.appendChild(el);

      window.setTimeout(function () {
        document.getElementById(id).innerHTML = text;
      }, 100);

      window.setTimeout(function () {
          document.body.removeChild(document.getElementById(id));
      }, 1000);
  }

Please remember that for vocalized messages to be hidden from the screen you must use a an accessible hiding class (visually-hidden) in your CSS.

Example

You can test this function with the form below (test it with a screen reader, otherwise you won’t hear anything).