Hiding content from screen-readers - and related questions - html

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

Related

Should ARIA buttons provide context?

(This question is similar to Should ARIA labels provide context?, but not identical, as I'm talking about buttons and do not have full control over the markup.)
I have some amount of items and buttons that act on those items. Here's a simplified example:
<ul>
<li><span>Item: foo</span> <button>remove</button></li>
<li><span>Item: bar</span> <button>remove</button></li>
<li><span>Item: baz</span> <button>remove</button></li>
</ul>
As far as I understand, when someone using a screen reader tabs through the page, they will be read the button text but not the item text. This doesn't seem ideal to me, as they don't have context on which item the button will remove.
Assume that I don't have full control of the markup; I can only add attributes.
What is the best practice in this situation?
add an aria-label to the button that gives more context:
<button aria-label="Remove item foo">remove</button>
make the item text itself tabbable and give it an aria-label so it's read aloud:
<span tabindex="0" aria-label="Item foo">Item: foo</span>
leave things as they are, because this is intended behavior and/or I'm misunderstanding something about screen readers
something else entirely?
The answer depends on if you're trying to conform to the Web Content Accessibility Guidelines and are only worried about compliance issues (from a legal perspective), or if you want to have a great user experience regardless of whether you conform or not.
The first part, conformance, is a little tricky. Regarding context, 2.4.4 Link Purpose (In Context) comes into play but only for links. The guideline says the text for a link is ok if the user can figure out the meaning of the link from the link text and the surrounding context (such as what text is before or after it). And then context is defined as the link being in the same list item (<li>) as the surrounding text.
So that sort of fits your scenario, but you have buttons instead of links, so WCAG 2.4.4 doesn't really apply to you.
There isn't a clear guideline for the context of buttons except WCAG 2.4.6 Headings and Labels. It says that the label [of a button] must describe the purpose of the button. So who decides whether the label is descriptive enough? That's a tough call. Is "remove" descriptive enough? Maybe, maybe not. It kind of depends who you ask.
So if you are focusing on a great user experience rather than conformance to WCAG, adding context to the buttons is a really good thing.
You are correct that if a screen reader user tabs through the interface, they will only hear the button label and not the list context. But screen reader users have many ways to navigate a webpage. One option is to navigate by list elements (<ul> or <ol>) by using the L key (JAWS and NVDA). Another is to navigate by list item (<li>) by using the I key. (That's the letter 'i', not a number 1). So a user can navigate to your list items, hear the text of the list and the text of the button and get some context.
I would not recommend your second idea of adding tabindex to the list. You don't want the user to tab to elements that are not interactive.
Adding more context via a label is the best approach. I would recommend using aria-labelledby before resorting to aria-label. If you have an element in the DOM already that has the text context you need, give that element an ID and then refer to that ID in the aria-labelledby of the button. It's a little more work but then you don't have to worry if you change the text in the list because the button is using an indirect reference and will automatically pick up the new text.
You'll also need an ID on the button and then you have the button point to itself and to the context. That sounds confusing but here's all it is:
<ul>
<li>
<span id='item1'>Item: foo</span>
<button id="button1" aria-labelledby="button1 item1">remove</button>
</li>
<li>
<span id='item2'>Item: bar</span>
<button id="button2" aria-labelledby="button2 item2">remove</button>
</li>
</ul>
A simpler approach is to use aria-label as in your first suggestion but I don't like repeating text in an aria-label that's already in the DOM. If your list text changes at some point, you have to remember to change the aria-label too.
Making the span focusable is a very bad idea unless it produces an action itself when clicked. Only elements that are actually interactive should be focusable.
It's very confusing for the user is something is focusable but don't provide any interaction when focused.
Adding context with aria-label is a good idea, but in fact there is better.
The recommended way is to add off-screen text instead:
<button>Remove <span class="sr_only">Item 123</span></button>
Where .sr_only is a CSS class present in many frameworks with different names (sr_only, visually-hidden, etc.) which send the text off-screen. It is invisible for normal users, but read as normal by screen readers.

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.

Accessibility: sr-only or aria-label

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>

Can I format HTML or CSS is a way that makes it easy for users to copy a block of text on mobile

I am looking for a way to format a section of my page so users can easily copy a small block of text while on a mobile device.
Are there any classes in Bootstrap, some HTML, or a way to format my CSS to make this easier. I know browsers except IE don't like javascript copying text to the clipboard.
Since your question is specific to HTML & CSS for mobile, here are some thoughts.
I find that having large hit areas available on the elements you want the user to interact can help to start with. E.g. paddings on <p>s for example. So when a user starts tap-holding to initiate text selection, it'll more likely fall on the hit area of the paragraph. (A nifty trick is replacing margins with paddings!)
Try to make sure your content that is selectable follow a natural content flow box model. No weird floats or absolutely positioned content or otherwise content that might confuse the selection widget. Make it as document-like as possible!
Read up on the ways that you can control selection, e.g. user-select CSS property - https://developer.mozilla.org/en-US/docs/Web/CSS/user-select
You might want to disable text selection on elements that don't make sense, to help make text selection cleaner on the parts that matter.
Large font sizes are obvious, but maybe not so obvious is very large line-heights is fantastic for making text-selection a little less awkward! It can improve readability greatly on the side as well, my favourite for body text is line-height: 1.6;.
If you use viewport meta tag, make sure they can zoom in to fill the text/paragraph edge-to-edge comfortably when they want to. This can help a lot to get up close, to do the text selection and get tactile with your content.
However, if you do want to try JS, then I would recommend clipboard.js: https://clipboardjs.com/
Think also about what your users want to copy ahead of time, you might be able to do some analytics and allow users to highlight common text. This is done on Medium by the way to lead as a good example.
You could make it so that when they click on the element, all the text is selected automatically, so all they had to do, assuming they're using a modern mobile device, is long-tap and press copy to clipboard.
document.getElementById("TextParent").onclick(function(){
fnSelect("TextParent");
});
So your html would look something like the following:
<div id="TextParent">
Click anywhere in this div to select this text!
</div>
Adding to this, Nexii Malthus has a good point in regards to the hit areas on mobile phones, so maybe try to add some extra padding to the div.
You should definitely try https://clipboardjs.com/.
<!-- Target -->
<div id="bar">Mussum ipsum cacilds...</div>
<!-- Trigger -->
<button class="btn" data-clipboard-action="copy" data-clipboard-target="#bar">
Copy to clipboard
</button>
and activate it using following javascript new Clipboard('.btn')
Look created sample https://jsfiddle.net/gevorgha/fbeof421/
Note
There are some compatibility issues with iOS devices that do not copy target on trigger action, but it selects target and allows user to copy it manually.

display:none, drop-down-menus and screen-readers

I have often read that using display:none for drop-down-menus (like done here) is bad practice, because it is inaccessible for screen-readers.
In this article: http://simplyaccessible.com/article/better-for-accessibility/ the author states that the position-off-left alternative from display:none has also downsides and suggests the following to make the drop-down-menu keyboard accessible:
Option 2: use display:none and have a :focus state to match :hover
that makes it display:block and brings the sub menu items onto the
page, allowing them to receive the focus, but only while they are on
the screen.
The :focus adjustment is realized with JavaScript. He gives an example on http://examples.simplyaccessible.com/css-menu/option-2.php.
Question 1:
Is the drop-down-menu from option 2 accessible for screen-readers? Do screen-reader read the complete page, and then you can tab through the page and they read out ever link? Would this means that the sub-menu is only read by the screen-reader when the person tabs through?
Question 2:
Using display:none has for me the great advantage that I can use jQuery functions like .slideDown() and .slideUp() which add a nice animation effect on the drop-down-menu. If I use position:absolute and hide the sub-menus off-left, how could I then get nice animation affects similar to .slideDown() and .slideUp()?
Answer 1: The simple answer is yes.
Longer answer:
Screen readers have a lot of options to move around a page, list out all of the available anchors, etc. NVDA, for example, also reads information via mouse interaction. Often, though, the focus of accessibility discussion is on keyboard users since they are often forgotten by developers. If a user is tabbing through the page, anchors that are visible (not display none) can have focus and be read. So the sub-menu is only accessible to the keyboard user (in option 2) when tabbing through the navigation. This applies to both visual and screen reader keyboard users. You can add your own keyboard interactions so content is available beyond tabs. However, keep in mind that the end user may not know how to use the menu. You'll also want to be mindful of keys already bound to screen readers.
Answer 2: Simple answer - you may want to consider CSS3 animations/transitions.
Explanation:
The slide aspect can be animated (if you have variable heights) using max-height and overflow hidden. So by default max-height of the sub-menu is 0 and then when the class is added you can set it to a number you think makes sense.
.menu li { position:relative; }
.sub-menu {
position:absolute;
top:100%;
left:0;
width:100%;
max-height:0;
opacity:0;
overflow:hidden;
transition:all 0.3s ease-in;
}
.active > .sub-menu { max-height:99em; opacity:1; }
If you make it 9999px the transition/animation look and feel will be influenced differently than 250px. Below is a simple CSS example of this:
Longer discussion point:
There wouldn't be much benefit for hiding the menu with position absolute off-left vs. display none for menus, if using an approach similar to the option you mentioned. You could get into a discussion on when JS is disabled and needing the content available then. Display none by default would prevent keyboard users from getting the content still (screen readers do understand Javascript, though). But the JS debate opens up further dilemmas, if we really want this to be perfect for all users without Javascript with different situations. With the content only visually hidden with the position absolute off left approach, a keyboard user who is a visual user will be able to focus on the anchors but won't ever see the content and may get lost (since it remains off screen).
So it isn't easy if we really want to account for all users in all situations. We have to set some restrictions sometimes and progressive enhancement is a possible aspect to keep in mind. Maybe the sub menus are only available to Javascript users. If interior pages have rail navigation of the sub section links then non-JS users regardless of screen reader user or visual keyboard user can still access all of the pages of the site.