Introduction
Sometimes, a web page may need to provide a message to assistive technologies that an event happened. For example, if a data table was resorted based on a column, a screen reader should be informed the table was successfully resorted. In general, any dynamic action that shows visual evidence may need to provide confirmation.
The Screen Reader Messaging (SRM) library provides a straightforward
means of passing a message to screen readers and other assistive
technologies via a visually hidden live region using the two ARIA
attributes aria-live
and
aria-atomic
.
This JavaScript library and supporting information are an open source project on GitHub released under the Mozilla Public License Version 2.0.
Basic Usage
Basic Usage Anchor LinkThe SRM library is designed for easy, straightforward deployment. One needs to only include the small script file:
<script src="dist/sr-messaging.js"></script>
After a short (<1s) delay after page load for the browser's
accessibility tree to recognize the added ARIA live region, the
messaging service is ready for use.
Whenever a message needs to be sent to a screen reader, just grab
the SRM messenger object and use the say()
method to
deliver the message:
let srm = ScreenReaderMessenger.getMessenger();
srm.say('Hello World!');
The SRM library uses the singleton pattern, meaning there is only screen reader messaging service available at any time. Each time you call getMessenger(), you will receive the same SRM object.
Demonstration
Demonstration Anchor LinkThe following demonstrates the screen reader messaging utility. Clicking the button returns the current seconds in the current time. This message is conveyed in three ways:
- The message "Seconds are #" is conveyed via the SRM to any active screen readers.
- The same message is logged in the textbox for debugging purposes.
- The same message is also logged to the console in the browser's developer tools.
The overall code for implementing the example is straightforward. More lines were needed to implement the timestamp formatting for the debug log! If the debugging feedback was not included, the code could be simplified to the following vanilla HTML and JavaScript:
<head>
...
<script src="dist/sr-messaging.js"></script>
</head>
<body>
...
<script>
window.addEventListener('load', function(event) {
document.getElementById('speak-trigger').addEventListener('click', function(evt) {
let d = new Date();
ScreenReaderMessenger.getMessenger().say('Seconds are ' + d.getSeconds();
});
});
</script>
</body>
Note how you can chain the getMessenger() and say() methods if so desired.
Additional Usage Notes
Additional Usage Notes Anchor Link- This library should only be used for informing of minor events to screen readers, such as a table being resorted or multiple disclosure panels being opened or closed en masse. It is NOT for reporting critical events such as alerts.
- As a rule of thumb, no messaging is necessary for interactions
that leave some evidence of happening. For example, opening or
closing a disclosure that sets
aria-expanded
does not need additional messaging. - Any and all messages should be short and concise so that they can be read within a window of time. The default duration for this window is 5 seconds.
- Do not send too many messages. If multiple messages are triggered at the same time, they will interfere and overwrite each other. This was a deliberate design choice to deter spamming screen reader users.
How it Works
How It Works Anchor LinkThe SRM library functions through the coordination of a DIV that is an ARIA live region and the ScreenReaderMessenger object that coordinates updating and timing of the message.
Creating an ARIA Live Region
Creating an ARIA Live Region Anchor Link
Once the page is loaded, the SRM appends a DIV element to the
DOM. This DIV element will temporarily contain the text of the
messages. Importantly, this DIV is styled so that it is shown
to only screen reader users. If the DIV was hidden using techniques
like display:none
, messaging
would not work.
This DIV's "invisible" styling is similar to other common
CSS
for invisible content for screen reader users. As it is
positioned absolutely, it should not impact the layout of any
site. The CSS also has extensive (and arguably necessary) usage
of the !important
property to
greatly reduce any styles undoing the invisibility.
The DIV is also an
ARIA
live region. Through the combined used of the ARIA attributes
aria-live="polite"
and
aria-atomic="true"
, the browser
will inform screen readers of any non-empty updates to the DIV's
text. Note that this live region is polite in that
the message will not interrupt any other messages from the screen
reader. The live region is also not given an ARIA role as none of
the currently available roles are appropriate. This messaging library
should NOT be used for critical announcements that would fall under a
role="alert"
situation.
The ScreenReaderMessenger Object
The ScreenReaderMessenger Object Anchor Link
Just creating a live region is not enough to provide dynamic
messaging to screen readers. The ARIA live region we created
only announces additions to the text content but NOT any
deletions. This works to our advantage. When the say()
method is called, the DIV's text content is initially reset to
the empty string. This does not get announced because it is
not an addition to the text. Then, the message is placed in
the DIV. This triggers the live region to inform the screen
reader of the new content. This also means that the same
text message can be communicated multiple times as the
reset then update process always triggers an addition.
However, there is a problem with this approach. Because the
DIV's content is not hidden to everyone, that text may be found
inconveniently through actions such as selecting all the text
or using a browser's find in page features. Thus, it is prudent
to always erase the DIV's text content eventually. The timing of
this is tricky, though. Some screen readers will
cease reading the text if it is deleted while being outputted.
Thus, you need to delay the erasing using a call to the
setTimeout
method in JavaScript.
The SRM handles this delayed erasing as well as making sure
no erroneous timeouts accidentally erase the text while it
is being read out loud. The internal variable
ERASE_DELAY
defines the delay, currently set to
5000 milliseconds (5 seconds). This delay mostly suffices
assuming that any message is concise enough. However, if
the screen reader's speech rate is set too slow, messages
may be cut off. If users report this is a problem, increase
the erase delay.
Acknowledgements
Acknowledgements Anchor LinkThanks go to Alex Umstead for develop his CodePen for creating a global live region and his conversations about the code itself.