0

I have an audio-element in my HTML whose only purpose is to make an announcement to blind users via a Screen Reader. It's a DIV, but it's invisible to regular users.

The way to announce something is by creating an element with role=alert (no other way to do it, there's no JS function to directly "speak" to a reader, for example):

<!-- This element can be dynamically added OR shown (via JS) to make a Screen Reader announcement -->
<div role="alert">This will be announced to Screen Readers.</div>

However, I can't have this "audio assistant" element be visible to regular users.

1) Can't use display: none; -> the Screen Reader won't pick it up

2) Can't use visibility: hidden; -> the Screen Reader won't pick it up

3) Can't use opacity: 0; -> because space is taken up, layout must be exactly the same

I found this solution: https://stackoverflow.com/a/25339638/1005607

div { position: absolute; left: -999em; }

This works great, it solves my problem. But it's a bit of a hack. I wanted to ask: Is there a better, more standard way to solve this problem?

gene b.
  • 10,512
  • 21
  • 115
  • 227

2 Answers2

3

It's a common practice to use CSS to visually hide an element but allow it to be discoverable by screen reader users. It's not necessarily considered a "hack".

There are more CSS properties needed than what you tried. See What is sr-only in Bootstrap 3? for details.

Also, you can search for the "visually-hidden" class.

Both sr-only and visually-hidden are common names used to name the class that visually hides elements.

Also, your understanding of role="alert" isn't quite accurate.

The way to announce something is by creating an element with role=alert (no other way to do it, there's no JS function to directly "speak" to a reader, for example):

role="alert" has an implicit aria-live="assertive". Elements with aria-live will announce changes to that element to screen readers. It will not automatically announce that element. For example,

<div id="foo" aria-live="polite"></div>
<button onclick="document.getElementById("foo").innerHTML = 'hello'">update</button>

When I click on the button, text will be injected into the <div> and the new text will be announced.

In general, you want to use aria-live="polite" and not aria-live="assertive". When you use role="alert", you get aria-live="assertive".

So if your page is updating its contents, then using aria-live is the right thing to do. But it does not cause something to be announced just because your page loaded.

The screen reader user has many ways to navigate a website using quick navigation keys defined in the screen reader (such as H to go to the next heading [h1, h2, h3, etc], or T to go to the next table, or L to go to the next list, etc.), provided your HTML is using semantic elements (such as <h1>, <table>, <ul>, etc). If you have text that is hidden to sighted users, then that text can be found by screen reader users without you forcing it to be read automatically.

slugolicious
  • 15,824
  • 2
  • 29
  • 43
1

I'm not sure if this is a "better" way, but this will hide it in place.

div {
  overflow:hidden;
  height:0;
  width:0;
}
Wayne Allen
  • 1,605
  • 1
  • 10
  • 16
  • that's not a complete answer. setting only those properties will not fully hide the element on all browsers and all screen readers – slugolicious Jan 22 '19 at 07:34