What is the best way to announce some text to screen readers (ie. role="alert", aria-live="assertive/polite")? - accessibility

I'm in the process of creating a searchable combobox component. It must be 100% accessible, so I want to tell screen readers how many results there are available when they open the component's options dropdown, and when they are changing its filter term.
The component looks something like this:
I think I will probably need a live region. I know two ways of doing this:
1) role="alert"
This is AFAIK the safest option: it used to work years ago already, and it is pretty well supported by all major browsers (Chrome/Edge, FF) and screen readers (JAWS, NVDA, VoiceOver/iOS, Talkback).
The bad thing: it is "rude", ie. it interrupts the screen reader's current announcement. In addition, some browsers add an ugly "Alert" as a prefix to each such announcement.
So for example, if the options dropdown is expanded (the user presses Down key after focusing the filter input), then two things happen at the same time:
The filter input's aria-expanded is set from false to true, which makes the screen reader announce expanded
The dropdown is now visible, containing a live region with text 4 of 12 options available, starting with "Badminton"
If this live region is a role="alert", then it potentially interrupts (⚡️) the expanded announcement, which feels like a hiccup from the screen reader, ie. expa⚡️ 4 of 12 options....
2) aria-live="polite"
This is the more gentle option: it will append the live region's content to the current announcement of the screen reader (instead of interrupting it), ie. expanded 4 of 12 options....
Sadly, this is not supported with JAWS+Chrome, as far as my tests show - can anyone confirm this? If so, this is extremely lame, taking into account that its the most used desktop combination, and behind both are multi-national (and probably multi-billion) companies.
Conclusion
I can't just use the gentle aria-live everywhere, I need to figure out which browser is used, and if it's Chrome, I need to reside to role="alert".
But there are more problems: there seem to be serious differences between how browsers (and/or screen readers) handle live regions:
Some have problems recognising a live region if it's first hidden (ie. hidden attribute, or display: none) and then made visible. It will then simply not be treated as live region.
Some immediately announce the content of such a made-visible live region, while others just ignore their initial content (they will only announce a change to it).
Some announce a role="alert" element even when it's already there when the page is loaded, others don't (and I think the latter ones are right, because as far as I understand, live regions should announce changes of content, not content that's initially there already)
So this topic is much more complex than I hoped. The simplest solution would probably be the following: just append a visually hidden role="alert" element at the end of the DOM each time an announcement is be made. Then, a few seconds later, remove it again. But this feels ugly to me. I'd rather have my live region right inside my component, where also visible users can see it, or at least parts of it: on the screenshot you can see 4 of 12 options for filter "d", but to screen readers, the same text is announced, plus some more details, ie. starting with option "Badminton". Keeping visual and screen reader announcement in the same place feels like good practice to me, so I will not easily forget about the latter ones, or I will spot some bugs quickly (that would otherwise may be not visible).
So my question is: is there maybe an existing script or library which solves this problem in a solid way and provides optimal experience for the most common browser / screen reader combos?
Thank you.

Polite live regions should be preferred. As you have noticed yourself, alert interrupts current speech, it's rude.
The prefix "Alert!" automatically added might even feel a little scary at times.
As you have noticed, polite live regions are working a little different on each browser + screen reader combinations. Some of these differences are intentional, others are just bugs, and others are simply due to the fact that the official specification doesn't clearly define any particular behavior.
This makes the whole thing, as you have said, actually quite complicated.
Sadly I have no universally working solution. In order to handle all cases, you need to make user agent detection.
Let's look at various issues or points of attention we have with live regions today (in may 2022).
I have no official reference, the following is only my own observations along the years:
Live region detection
A live regions is successfully taken into account as such only when aria-live attribute is present when the element is added to the DOM, and when it is visible by screen readers.
This, in particular, means that it isn't taken into account when the aria-live attribute is set after the element has been added in the DOM, when the element is display:none, visibility:hidden, when attributes aria-hidden or hidden are set, or when the size is 0. Even if hidding attributes are removed later on, it doesn't work.
Announcement time
The only two cases when the content of a live region has to be announced are:
When the element is added in the DOM
When the content of the element has changed
For all other cases, it isn't well defined in the specification. In particular, initial content present directly in HTML code may not be announced, and as far as I have already observed, none of the browsers I have already used ever announce initial content at page load.
Interruptions
When an assertive live region is added, speech is normally always interrupted. Polite live regions updates should never interrupt speech.
However, with many browsers + screen readers combinations, a content currently being read is shut up:
When the aria-live element is removed from the DOM
When its content is emptied
This is for example the case with VoiceOver both under iOS and mac.
So if you have multiple messages to be spoken potentially quick in succession, you shouldn't just replace the older message by the newer one.
You can adopt several strategies:
Simply append new messages to the already existing live region
Create new live regions each time
Clear live region content or remove it from the DOM only if the last messages is older than a few seconds ago
But, be careful, that's not all.
Repeat or not repeat
With some browsers + screen readers combinations, if you simply append new messages to be announced at the end of a live region, the whole content is repeated over and over again from the beginning.
In short, the whole content is read each time there is a change, even parts that haven't changed.
IN theory, the standard provides the two attributes aria-atomic and aria-relevant to control this behavior.
Defaults values are aria-atopic=false and aria-relevant=additions, meaning that only the new content has to be read, and content that hasn't changed shouldn't be read again.
However, in practice:
Chrome with both Jaws and NVDA ignore these attributes completely. The whole content is always read at every change no matter what.
With Firefox and Jaws, the aria-live region no longer works when aria-relevant attribute is explicitly set
With at least some versions of Safari, the aria-live region doesn't work if aria-relevant=additions isn't explicitly set
With some versions of Chrome, if for any reason you want to speak twice the same message, replacing content doesn't work, even if you replace first by the empty string and then by the content again
Are we safe if we create a new live region for each message? Spoiler alert: no!
Announcement order
When several live regions are added to the DOM or updated quickly, nothing says which one has to be announced first.
Safari iOS seem to handle it correctly, i.e. read content in the order of update. I don't know on mac.
With Chrome and both Jaws and NVDA, updating quickly several live regions seem to make them being read in reverse order of their position in the DOM.
Conclusion
At present, it looks like the safest is to create new polite live regions for each message.
You can reuse them, but only if new messages don't arrive too quickly, or if it doesn't matter if they are occasionally interrupted.
For your particular case, I would say that a single reused polite live region is sufficient.
But of course the best is to test as many combinations as possible.
Good luck.

Related

Do accessibility settings like 'aria-hidden' prevent Power Automate from clicking or pressing content on a web page?

I am trying to select a dynamic calendar on a website. My goal is to open the calendar and input dates as I need to. I am not able to open the calendar by "Press button on web page" or "Click link on web page" with my selected UI Element. There are no ID's available to select. I have tried using the div class names with no luck. I have tried altering the selector to make a custom selector that looks for div names containing part of the class name. The 'Name' attribute in Power Automate is unavailable for the UI Element.
After trying all this, I noticed an Icon that is part of a div for the calendar, has
aria-hidden="true"'. When I checked the MDN here it has a warning statement: "Warning: Do not use aria-hidden="true" on focusable elements."
With being unable to select the calendar with standard and custom selectors, am I being blocked by the accessibility setting? Is Power Automate unable to focus on the calendar opener from aria-hidden="true"?
I don't know power automate, but what you observe makes sense. The attribute aria-hidden=true tells assistive tools such as screen readers and voice control software to ignore the element, as if it wasn't present at all.
A focusable element must never be aria-hidden=true. A screen reader won't know what to say when landing on it, and, as observed, it won't be reachable using voice control.
That's simply a pure accessibility fail (I would even call it stupidity, but well).
Technically, the solution is very simple: remove that stupid offending aria-hidden=true. Those who made that calendar probably put it there because:
they thought that screen reader and voice control users will always enter a date by hand and won't ever use the date picker
the date picker hasn't been made accessible, and so it's better to ignore it completely rather to present something only partially accessible
They copy/paste the code from elsewhere and didn't pay attention
They have no excuse for the third one, and for the two first, both reasoning are just wrong. Even if it isn't perfect, it's better to have a little something rather than nothing.
Keyboard-only user or screen reader user don't necessarily mean eased to enter a date manually. ON a mobile, the virtual keyboard is often painful to use, and people with limited movement sometimes use a device with only a few available keys (such as enter, tab, escape, and arrow keys only). Additionally, both might be combined if you think about someone who has a strong dyslexia and an inability to use his hands (the device would be actioned with feet, blinking eyes, etc.).
In theory, you shouldn't ever use custom widgets if you can avoid it. For entering dates, the standard exists: input type=date and friends.
Using standard widgets is the best guaranty to have something accessible at long term. Even if it might not be 100% accessible right now, it's getting better as the time passes.
Sadly, UX designers often don't like standard widgets much because it doesn't look like what they want, and there are still a few older browsers which don't support them all very well.

Accessibility - provide mechanism for easy navigation between interactive sections

We have a web-based app which uses a side-by-side experience for desktop users where the left side of the screen is a file browser and editor and the right side of the screen is an interactive preview. Users of our app will make constant and iterative changes on the left and and then interact with the preview on the right, switching back and forth many times in quick succession.
Is there a "best practice" for allowing quick and easy navigation between these two interactive areas? I know this might fall under the "opinion" category, but I feel that accessibility is such an overlooked topic that it helps to have as many resources as possible.
You have a few tools at your disposal.
Headings
Headings are one of the easiest ways to bake in some super simple section switching. Screen reader users will use the keys 1 through 6 to navigate by heading levels so if both of your panels are <h2>s (for example) they can simply cycle location using headings.
Keyboard shortcut keys
You can set keyboard shortcut keys.
However you should never do this in isolation. By this I mean if you say that switching window is say Alt + 0 you must allow users to be able to change these key bindings to their preferences.
This is so your shortcut keys don't interfere with their screen reader keys (as they may have set custom keyboard shortcuts).
please note: as pointed out in the comments this is not a WCAG requirement for key combinations (which is only for single keys) but is a usability best practice and highly encouraged, especially as some screen reader users use a modifier key rather than a toggle key for screen reader navigation.
Then we get into an interesting area which I like to illustrate by saying "how would a one handed user use your page?".
This example makes you realise that some sort of sticky keys solution may also be considered where key combinations can be done with a sequence of keys, any time apart (as you may have someone with NO HANDS using eye gaze technology or a switch for example so you don't want to impose a time limit.)
Obviously the above are extreme examples but things you may want to consider (and in reality anyone using eye gaze would be able to visually switch panels etc.)
Voice commands
Being able to switch panels via voice (for example Dragon Naturally Speaking) is also essential.
Now you can do key combinations with voice software so that fixes most issues but they can be annoying and fiddly.
One thing that is quick to use on most voice software is clicking any button on a page with a unique name.
As such having a button above each panel that activates it would be beneficial to voice users.
Assuming these buttons have unique names I could simply say "click activate panel 2" (where "activate panel 2" is the button name) and switch immediately.
Do you need to manage focus?
Bear in mind that when you switch panels you will by default start at the top each time.
This may be exactly what you want but more than likely this would be a terrible user experience.
Instead you may want to remember the previous focus location. Then if I use the keyboard shortcut it would jump back to the same location in the panel. If I use the voice / button click to change location same again.
However if someone uses headings to navigate this obviously wouldn't work. You could then give them a button directly after the heading that says "resume from previous location" to fix this and use that to manage focus.
User settings
As you can see there are loads of things that different people with different requirements may or may not need.
As such adding all of the features by default would probably make the application worse to use for majority of users.
Instead have a settings screen that lets a user turn on features that benefit them, set their own shortcut keys, turn on or off sticky keys, decide if they want you to manage focus for them (or not) etc.
This is a difficult problem! I have been giving a similar issue a lot of thought. I have outlined one idea that uses ARIA live regions, and an alternative idea that might work better if quick-jump keyboard support is vital.
Live region announcements as part of a <form>
The <output> tag may be what you're looking for. It is mapped to the ARIA role of status so any changes to its content will be announced without any focus change. That way, the user can continue to navigate and make changes on the left side without always having to flip over to the right side to know what changes were made.
The role status has an implicit aria-live value of "polite", so that the announcement will wait until any other descriptive announcement is finished.
It has an implicit aria-atomic value of "true", which means that any change will trigger the announcement of the entire contents of the element -- which may or may not be appropriate for the content. If not, add aria-atomic="false" to read out only the changed node.
If the content inside the <output> could be anything other than phrasing content (including <div>s or heading tags) then you should use a <div> with the role attribute of "status" instead.
Custom keyboard controls can get tricky with various types of assistive technology (AT) software/hardware. Plus those commands probably can't be made easily discoverable. Some ATs provide a keyboard command to flip between a controlling element and the element assigned via its aria-controls attribute. Unfortunately, this functionality is poorly supported, but it is the current standard, so support may get better over time. Currently only NVDA on Windows supports it, with the keyboard command Insert + Alt + M.
Adding aria-controls to an element controlling an <output>/status is mandatory anyway, so give it a unique id attribute and set that as the value of aria-controls on each form element inside the <form>.
If the <output>/status is wrapped in a <fieldset> and the inputs are all wrapped in a containing <fieldset>, then each <fieldset> acts as a grouping container, so the user can navigate between them quickly. As part of this, ensure the <fieldset> containing the <output> directly follows <fieldset> containing the form elements in the source order. If this isn't possible, add the aria-owns attribute to the containing <form> and reference the id attributes of both <fieldset>s with a space in between.
Always-open non-modal <dialog>
You may instead consider making the right side pane an always-open non-modal <dialog>. A <button> next to each interactive element on the left pane would move focus to the <dialog>, and the Escape key would return focus back to the <button>. Focus isn't trapped within a non-modal <dialog>, so the user can still move between each pane using normal navigation methods. The <dialog> needs to have an open attribute to appear and it also needs to have aria-modal="false".
Each <button> would need an aria-controls value referencing the <dialog>'s id attribute, and an aria-haspopup value of "dialog". The <button>s could be invisible until focused.
There's only a single focused point at any given time. So there isn't any real miracle solution, screen reader and other keyboard-only users will necessarily have to repeatedly go back and forth.
IN fact, the most important isn't to be able to switch quickly between the different parts (you must only somehow give a way to do it only with keyboard), but to not lose cursor position when you switch.
For example if I edit something on the left, go to the right to check the result, and then go back to the left side, I expect to find the insertion point exactly where I left it off.
You really have to make sure that this is always correct, and as closest as possible when changes occurs (especially when it's asynchronous, i.e. a change occurs on the right side when you are on the left side).
The most similar accessibility recipe or component is probably split view.
In windows world, the most used shortcuts for cycling between the different splitte parts is F6, and Shift+F6 to cycle in reverse direction.
Don't hesitate to add other easier or additional shortcuts if the switch has to be really frequent, such as Ctrl+Tab, if such shortcuts aren't already used for something else.
F6 and Shift+F6 aren't the easiest shortcuts to perform, especially on laptops where all F1-12 keys may not be available at all or only by using an additional FN key. I personally always found F6 a questionnable choice, but that's only an opinion; at least we have something and that's of course better than nothing.
However, don't replace an existing shortcut commonly used. (for example Ctrl+Tab = switch between different tabs, don't use it for cycling between views if there are tabs in your application and keep it for the tabs)

Only show focus states once tab navigation has been used

I'm working on a site that requires WCAG 2.0 AA adherence, but although we try to make tab navigation usable on our sites, it does detract heavily from the design due to the strange borders and outlines being rendered when you click a focusable element.
My thinking is, hide all focus states until the tab key is actually pressed.
So, my question is, does this pose any potential problems with accessibility technologies for the web?
Remember that sometimes focus is placed on elements without using a keyboard, such as via script or third-party tools (like screen readers prior to page interaction). Also note that even screen reader users do not necessarily use the Tab key (for example, I can navigate the headings on a page by pressing H in most screen readers, and on mobile I can navigate a page elements without using a keyboard at all. Also note that some users with cognitive impairments benefit from focus styles even when using a mouse.
As such, if I were reviewing a site that disabled focus styles only until someone pressed the Tab key, I would still fail it for 2.4.7
Focus Visible. It might be helpful to read the Understanding SC 2.4.7 document for a little more context.
To answer your question, yes, removing it does post potential accessibility problems.
All that being said, I would instead challenge the designer to do what designers tend to do best — work within constraints. Come up with focus styles that are not distracting, with styles that are perceivable, operable, understandable, and robust (so, for example, it meets contrast minimums). It has been done before, so there is no reason it cannot be done again.

Is there anything that shows what works/doesn't for various screenreader/browser combinations?

I'm enhancing the UI for an application to be more compatible with screen readers. The problem is I keep running into issues and I'm beginning to suspect that it' due to the screen reader itself.
Right now I'm mostly testing JAWS 15 with IE 8 (due to corporate limitations it's basically all I can test with at the moment) and getting some weird behavior, but as near as I can tell the aria markup and html all look correct.
For instance:
In some hidden divs (role="alert") the JAWS does not speak "button" after reading a button's name after the DIV is show. (It does speak "button" once you tab to the button though.)
JAWS is speaking elements with aria-hidden="true," which was fixed according to this thread.
Again with hidden alert divs, in some cases JAWS will repeatedly speak elements. In at least one case it will repeat the header and the first line of text infinitely (or at least until my patience ran out.)
The altText for images in table is not read when the entire page is first read. It does get read when the user navigates through the table with the table commands though. I don't even know what corret behavior is on this one...
I'm basically looking for something where I can find out if these are known issues with JAWS/IE8. And if there's a list of compatibility out there (similar to the HTML5 compatibility list) I'll be able to refer to it whenever people bring these issues up.
http://html5accessibility.com/ is a starting point to discover whether a browser has accessibility support for native elements and attributes.
If you're looking for documentation of screen reader support for ARIA attributes, check out The Paciello Group. For example, Steve Faulkner published a post on role=alert that may be helpful.

Website accessibility rundown - rules, things to do, tips, etc

Accessibility is important to me as I'm a physically disabled developer. I'd like to make sure I have a good feel for what it takes to make a site accessible while also being pointed in the right direction for the things I'm uncertain with, or just haven't considered. So, here's what I'm comfortable with right now:
Alt text for images with meaning.
Percentage or font-relative measurements (ems) for those who need to re-size their screens.
Colors with good contrast for those with colorblindness.
Textual representation of any audio/visual material.
Questions:
Should I make a link at the top of the site to jump down to content on every page?
How is JavaScript handled by screen readers?
Is there anything major I'm missing?
WebAim.org is a great resource for all things web-accessibly related. Suggest starting off with their WCAG (Web Content Accessibility Guidelines) checklist.
Quick answers to your qu's:
Should I make a link at the top of the site to jump down to content on every page?
This is currently recommended best practice. (Eventually HTML5 semantic tags will remove the need for this, but we're not there yet. One thing to watch for: if you do use a hidden link, be sure to make it visible again when it has focus, so that sighted keyboard users don't get 'lost'.)
How is JavaScript handled by screen readers?
All depends on what you use it for. The main area for problem is if new content appears that the user is supposed to be aware of (eg. popups, expanding blocks); if it doesn't get keyboard focus, a screenreader may not read it out to the user and the user may not realize that anything has changed. This is one area where it may be necessary to test with a real-world screenreader (eg. NVDA or JAWS) to ensure that it's actually usable. A simple approach is to only have UI appear in response to user request: eg user hits return on a menu item to make the menu appear, don't make it appear merely in response to it getting focus. Then when it does appear, set focus to the first item: this is both expected behavior for menus in most UIs, and changing the focus typically also causes the screenreader to read out the new item, which confirms to the user that something has happened. (Also, if using Javascript to add behavior to existing elements - eg. make a link behave like a button - use WAI-ARIA attributes such as role="button" to let the screenreader know what the intent is so it will read out that role to the user, and will say 'button' instead of 'link'.)
Is there anything major I'm missing?
I think you've got most of the key points already covered above; the WCAG checklist should fill in everything else. One major area that is worth mentioning is to use headers (H1, etc) appropriately. For screenreader users, navigating by header is a major way for navigating a page. Typically when navigating to a page that a user hasn't visited before, the user will hit a hot-key to get the screenreader to bring up a list of headings on that page as a way of 'skimming' to get an overview. Having good link text is also important; ideally links should be self-describing, so you don't just hear "click for more", "click for more" as you tab through a page.
For newer browsers, IE8, IE9, Firefox 3?, and Safari 5 (possibly 4), and newer screen readers WAI-ARIA is the way to go. Among other things it has landmark roles which if you have an ARIA reading screen reader, such as JAWS 12 and possibly JAWS 11 and 10, the screen reader can use to jump around. It can get a bit clunky if you want things to be backwards accessible but is the direction the web is going in. Their are many other advantages to ARIA but that's the one relevant to your question. On a related note VoiceOver for the Mac is supposed to be ARIA compliant as well.
I'm not disagreeing with the selected best answer, but I would spend more time learning about WCAG 2.0 than with the original WCAG specification. Both in the United States and internationally, the Web Content Accessibility Guideline 2.0 are quickly becoming the standard. In fact, the Access Board, the group tasked with defining the guidelines for Section 508, are refreshing the standards to be harmonized with WCAG 2.0.
You can find great information by starting here Web Content Accessibility Guidelines (WCAG) 2.0.

Resources