Search code examples
javascripthtmljqueryaccessibilitynvda

Focusing Element Prevents role="alert" Content From Being Announced


$(document).ready(function() {
  $('#submitButton').click(function (){
    $('#password').focus();
    loadSRValidationMessages('#alertContainer', '.adhocError');
  });
});


function loadSRValidationMessages(n, t) {
    $(n).empty();
    var content = "";
    $(t).each(function() {
        var t = $(this).text();
        if (t.length > 0) {
          content += "<p>" + t + "<\/p>";
        }
    })
    $(n).append('<div id="alerts" role="alert" aria-atomic="true">' + content + '</div>');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<div id="alertContainer">

</div>

<form id="loginForm">
  <input type="password" id="password" required><br/>
  <label class="adhocError">An example error.</label>
  <button type="button" id="submitButton">Submit</button>
</form>

What I would like to present is an issue in which it seems as though focusing on an element interrupts, or perhaps prevents, the screen reader (NVDA) from announcing new role="alert" content. I have performed some research and looked at some existing Similar questions, though have yet to find a solution (ideally, having the screen reader announce new alert content as well as focusing on an element).

I have a simple scenario using jQuery. The code is abbreviated. Please let me know if you find any other information necessary.


Solution

  • Due to the way the role="alert" element works in some browser / screen reader combinations a more robust way is to add the full alert message and it's container to the page, rather than updating the text within the container.

    If you need to issue multiple alerts you should just add multiple alert containers to the page (and ultimately remove the old alert containers, either via a close / dismiss button or when the alert is no longer relevant).

    If you want to add multiple updates to a page, a better tactic is to place an aria-live="assertive" region onto the page and add / update content within that.

    I find that the best way to handle updates for screen readers in a web application is to have a single aria-live="assertive" region on the page and have a central message queue in JavaScript (JS), with a delay between each message.

    If you have something like a chat application or something that is not "urgent" that you don't want to interrupt a screen reader user with a second aria-live="polite" region can be added (using a second messages queue handled by JS).

    That way you end up with two simple queues to add messages to messages.assertive and messages.polite and you will eliminate a load of problems associated with lots of aria-live regions (which include role="alert" regions).