Accessibility: sr-only or aria-label - html

From MDN:
In the example below, a button is styled to look like a typical "close" button, with an X in the middle. Since there is nothing indicating that the purpose of the button is to close the dialog, the aria-label attribute is used to provide the label to any assistive technologies.
<button aria-label="Close" onclick="myDialog.close()">X</button>
According to the Bootstrap Documentation:
Hide an element to all devices except screen readers with .sr-only
So I guess I could also write:
<button onclick="myDialog.close()"><span class="sr-only">Close</span>X</button>
In a Bootstrap project, how can I choose which one to prefer?

In the MDN example, a screen reader will just speak just the word "close" since aria-label overrides the text in the button. This will work even if you re-use the code without Bootstrap.
In your example, a screen reader will speak "close x" since you are doing nothing to hide the "x" from screen readers. You are also adding a text node to then hiding it with a class.
I would use the example from MDN.

The class sr-only class is for whole blocks of text content which are only useful to those using a screen reader and should be hidden from others.
An example from and app I'm working on provides instructions for using an accessible controller with the web app:
<div class="sr-only">
When voting with the text-to-speech audio, use the accessible
controller to navigate your ballot. To navigate through the
contests, use the left and right buttons. To navigate through
contest choices, use the up and down buttons. To select or
unselect a contest choice as your vote, use the select button.
</div>
In your example, you simply want to provide different text content for a screen reader. To answer your specific question, use the MDN example.
I've use aria-labels to hint to a screen reader when to add pauses by suffixing titles with periods or commas as necessary (More about Pausing in a screen reader for accessibility):
<h1 aria-label="Hello World.">
Hello World
</h1>

Related

Force screen reader to read acronym by his full name

How can I force a screen reader to read M as Monday? (using https://www.nvaccess.org) I would like to have it more WCAG friendly
Problems:
div don't support aria-label (https://www.tpgi.com/short-note-on-aria-label-aria-labelledby-and-aria-describedby/)
M isn't clickable (so I shouldn't use button etc.)
no space for full name (Monday)
code and visual:
<section>
<div aria-label="Monday">M</div>
<div aria-label="Tuesday">T</div>
..
</section>
The wording of your question suggests using <abbr>.
You may use it, but in this case you cannot force screen readers to always read the full expanded text instead of the abbreviation.
Screen readers generally provide options whether to expand abbreviations all the time automatically, only on demand, depending on context, or never.
This is something under control of the user, who can choose what is the best for him/her. You shouldn't dictate it at his/her place.
However, looking at your particular case, you are in fact probably not looking for abbreviation and <abbr>.
As you have well identified, you are more looking for a kind of label that has to be read full text all the time.
As you have well identified too, you can't use aria-label, since aria-label is reserved for interactive elements, what your element is precisely not.
IN that kind of circunstances when you need a kind of label outside of interactive elements, a good solution is to use visually hidden text, like this:
<div>
<span aria-hidden="true">M</span>
<span class="sr_only">Monday</span>
</div>
Where sr_only is a CSS class which puts the text off screen.
You can find the CSS code of .sr_only in bootstrap. Many other frameworks have similar visually hidden text CSS classes with other names.

Should buttons have labels from WCAG point of view?

I am building an app which has to be WCAG compliant. It requires about 12 buttons. Some of the buttons have only tooltips and icons but no labels. I haven't been able to find clear cut language in WCAG about this problem. Are titles necessary for buttons?
Short answer
Yes, your button must have so form of text label associated with it.
But don't be confused with <label>, which is normally unneeded for a button.
Long answer
The answer isn't answered directly in WCAG, but this is a question of perception, which is the first WCAG core principle.
If your button has only an icon but no alternative text or label, it follows that screen reader users won't perceive your button.
So, in the broad sense, yes, your button must have a kind of label.
You have several ways to set an accessible label, technically known as accessible name, to a button having no text itself:
Attribute alt of <input type="image"/> or the <img/> which is inside the button
aria-label or aria-labelledby attributes
Visually hidden text
Don't be confused with <label> element. It's unneeded for a button, since a button usually carry its own accessible name.
An <input type="text"/> need a separate <label> because it has typically no accessible name otherwise.
This may also be a question of understandability, which is the second WCAG principle.
Even for perfectly sighted people, are you sure that the meaning of your button without any text is crystal clear ? Few icons are known to be almost universally understood by everybody without any hint, any help, any tooltip, nothing.
IN that quite small list you can certainly find multimedia buttons (play/pause/stop/record), parameters/settings wheel, power on/off, but probably not many more.
As a consequence, the question isn't only about having an accessible name for screen readers. It goes much beyond that.
To wrap up, yes, your button definitely must have some form of text label associated with it.
Short Answer
You should add aria-label to your buttons.
Longer Answer
Buttons need a name that can be computed for accessibility. First to answer your questions:
Are titles necessary for buttons?
No
Should buttons have labels from WCAG point of view?
No once again, in fact they are probably not valid.
So what should I do?
Buttons don't need titles or <label>s (in fact a <label> on a button would probably not be valid without some WAI-ARIA).
But, they do need to have an accessible name, and I think this is the part that is causing confusion.
Because your buttons only have an icon and a tooltip, they probably / possibly do not have any text that is useful to assistive technology (such as a screen reader).
So when they reach a button with just an icon using a screen reader they will hear "button", with no indication of what the button is for!
The fix
There are several ways to approach this, but the easiest is aria-label.
WAI-ARIA is a set of attributes you can add to HTML elements to add extra meaning / semantics to make a page make more sense to assistive tech users.
The aria-label attribute, when used on an interactive element (such as a button, an anchor / hyperlink etc.), will indicate the the browser "hey, please present this as the accessible name for this element.".
So in your example, something similar to the following would ensure that the purpose of a button is clearly described:
<button aria-label="Add New Document">
<!-- your icon -->
</button>
So instead of just saying "button" when focused it will now say "Add New Document, button".

Hide Element but Preserve for Screen Readers (can't use display:none, visibility:hidden, or opacity: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?
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.
I'm not sure if this is a "better" way, but this will hide it in place.
div {
overflow:hidden;
height:0;
width:0;
}

Hiding content from screen-readers - and related questions

Intro:
I'm coding a single-page app. It's a sort of e-book reader and I want to optimize screen reader experience.
For general performance reasons (load times, HTTP requests) all of the functional components of the app are always present in the DOM, visibility managed by CSS. Only the actual content is dynamically loaded.
That means there's a lot of stuff present that is not needed all the time, e.g. the login/register pages.Sighted users won't know, but screen reader users could be annoyed.
There's also things that I figure shouldn't matter to screen reader users, like a bunch of visual options (font size, colors...).
What I intend:
I want to hide certain sections by applying aria-hidden="true".
I want to dynamically apply that to elements which are not currently functional, like the register page for a logged in user.
Also, I want to generally hide certain "presentational" sections, like visual options.
Questions:
Is that good practice?
Are there drawbacks?
Is it necessary?
Are there other/better ways of telling sr users that elements are of no use to them?
and, last no least,
Are there good ways of directing the attention of sr users to certain elements?
-
p.s. I have already structured the DOM sensibly, like
<body>
<main role="main"></main>
<nav role="navigation">
<button>Next Page</button>
<button>Previous Page</button>
...
</nav>
<menu role="menu">
<ul>
<li><button role="menuitem">Important Task</button></li>
...
<li><button role="menuitem">Least Worthy Task</button></li>
</ul>
</menu>
<div class="options">
...
</div>
to make sure that the controls should be tab-focused in descending order of use frequency.
I assume that the act of changing page would remove/hide the current content and unhide the new page? In which case it sounds like you are taking a good approach from a showing/hiding point of view.
I did a quick gist / cheat sheet recently of current best practice for: hidden from all, hidden from screen readers, or shown only to screen readers:
https://gist.github.com/alastc/7706437
For items which are currently not active but disabled, it might be inconsistent (and therefore confusing) to hide them? Perhaps use the disabled/aria-disabled attribute instead.
As the content and next/previous are first in the order, having several disabled controls after those should be fine. NB: When reading screenreaders have a 'browse' order that follows the DOM and is not affected by tabindex. You're order looks good, so don't try and over-ride it with tabindex.
Also, please pay attention to keyboard focus. I.e. when you select 'next', does the keyboard focus move to the top of the next page? I wrote an answer about the keyboard focus aspect for single-page apps.
Also, as you have multiple nav elements it would be helpful to label them, then they could be announced as "Page, navigation" and "Options, menu" (for example).
Take a look at the following link. It lists ways to hide content from screen reader users as well as what combinations of screen reader and browsers behave properly.
http://www.html5accessibility.com/tests/hidden2013.html
Your approach will work however you are over thinking things.
Any content hidden in CSS with display: none or visibility: hidden is also hidden to screen readers

Change html element accessibility text

On a webpage I have a div
<div class="expand">+</div>
Tapping this div expands content.
I need to change what screen readers say when they encounter this element. I've been able to come close with:
<div class="expand" role="button" title="Tap to expand">+</div>
If you tap the button, the iPhone will say
Plus ... Button ... Tap to expand
Ideally it would just say "Button ... Tap to expand," or I could have complete control over what is said.
Additionally, tapping changes the content and the title to "Tap to hide." The element is focused immediatley and the new content is read, but for some reason the title is not included this time:
Hyphen ... Button
If you tap it again it will say the title.
Is there any way to control what is said by the screen reader when you tap an element? If not, is there any specific rule that prevents the title from being read in the second case?
Suggestions from http://alxgbsn.co.uk/2011/06/06/making-web-content-more-accessible-with-ios-voiceover/ made this possible.
<div class="hide" id="tap-show">tap to expand</div>
<div class="hide" id="tap-hide">tap to hide</div>
<!-- repeat -->
<div class="expand" role="button" aria-labelledby="tap-show"></div>
You can use JavaScript to change aria-labelledby, which works.
It is important to note that the role=button is necessary and the <div> must be empty. It can contain at most whitespace. You can use a background image, or:
.expand:after { content: "+"; }
In general you should be very careful about controlling this text exactly. People using screen readers use many apps / sites, and get used to how things are read out. In the case of button text, VoiceOver will generally announce:
[Content of button]... Button... [title of button]
If this is specific to iOS then I think your initial example is good, as VoiceOver considers the title to be 'help text', which is why it's read last. Assuming you have quite a few of these, then brevity is good.
Hyphen doesn't mean much, but you could use − to get it to announce "minus", and update the title to "Tap to hide".
Something you might consider including as hidden text is what it is that will be shown. Perhaps in your interface it is obvious visually and from a screen reader point of view, but in general it would be useful to know what is going to be shown.
You could hide some text, for example:
<div ...>+<span class="hidden"> description of the content</div>
Then move the .hidden off-screen with CSS.