For my accessibility related question, I googled "accessibility shopping cart" and visited many popular online stores but didn't find a clear answer on my question. From the accessibility point of view, for the shopping cart, should I add a tabindex="0" (the code is slightly simplified) for
<ul>
<li><span tabindex="0">Merchandise: $40</span></li>
<li><span tabindex="0">Shipping: $10</span></li>
<li><span tabindex="0">Taxes: $0.40</span></li>
<li><span tabindex="0">Total: $50.40</span></li>
</ul>
or simply
<ul>
<li><span>Merchandise: $40</span></li>
<li><span>Shipping: $10</span></li>
<li><span>Taxes: $0.40</span></li>
<li><span>Total: $50.40</span></li>
</ul>
, or separate merchandise and $40 as
<li><span tabindex="0">Merchandise</span>: <span tabindex="0">$40</span></li>
, or even add (if Twitter Bootstrap is used with its sr-only class)
<li><span tabindex="0">Merchandise</span>:
<span tabindex="0">
<span aria-hidden="true">$</span>40<span class="sr-only"> American dollars</span>
</span>
</li>
The main question you should ask is: are all these list items interactive ? Does it happen something when they are clicked ?
If your answer to this question is yes, then you should add tabindex=0 so to make the interactive element usabe by keyboard only users. If you don't do it, then your site isn't accessible for them.
If your answer to this question is no, then tabindex=0 useless and even counter-productive. Keyboard only users will have to press tab more times to skip your elements which do nothing, and reach actual useful elements. That's a waste of time and usabiility.
Of course, in reality, it's more complex than just that. For example, an element may be interactive at some moment, but not at some other moment, in which case tabindex=-1 should be used to disable focusability when it isn't desired.
But here are the basics.
If you don't have any good reason to add a tabindex="0" (some custom interaction with these elements that is not explained in the question), you must not add tabindex="0" to your elements.
Screen readers provide controls to simply read within a page, instead of interacting with components. Interacting with list items that simply show prices would be unexpected.
<ul>
<li>Merchandise: $40</li>
<li>Shipping: $10</li>
<li>Taxes: $0.40</li>
<li>Total: $50.40</li>
</ul>
I deleted the <span>, it's not necessary for accessibility (you can keep it if you need it for any other reason).
Regarding the .sr-only question, it's also not necessary. For example, Voice Over reads $40 as "forty dollars".
You should simply leave the list as-is, without tabindex, but could help users skip the list of products in the cart by providing headlines:
<h2>Products</h2>
…
<h2>Summary</h2>
<ul>
<li>Merchandise: $40</li>
<li>Shipping: $10</li>
<li>Taxes: $0.40</li>
<li>Total: $50.40</li>
</ul>
The expectations for a shopping cart are the same for screen reader users and non-sr users: Some interaction is available to remove products or change their number, but mainly they read to make sure they got everything.
Screen readers provide controls to read within a page, instead of interacting with components (that would be tab). Even tables are not read in an interactive or form mode.
They also provide shortcuts to jump to the next headline.
If there is interaction
Should you actually provide interaction on these <span> elements, by binding keydown and click handlers, you’ll need to communicate the nature of that interaction, by assigning a proper role to these spans, like role="button".
On providing different texts to screen readers
In most cases it’s not recommended to make screen readers announce texts in a certain way. They do have logic implemented already, and their users are accustomed to that. VoiceOver announces $40 as ‘fourty dollars’, for example. Users can also customize how certain things are announced, which should be respected.
First, you should add the <ul> or <ol> tag around the list. The screen reader will then announce how many elements that are inside the list. Jaws will announce the example list as: "list with 5 elements". tabindex only makes the elements tabbable with the "TAB" key, remember to add a focus indicator as well.
<ul>
<li><span tabindex="0">Merchandise: $40</span></li>
<li><span tabindex="0">Shipping: $10</span></li>
<li><span tabindex="0">Taxes: $0.40</span></li>
<li><span tabindex="0">Total: $50.40</span></li>
</ul>
It can be wise to separate the product and price for each list element:
<ul>
<li><span tabindex="0">Merchandise</span>: <span tabindex="0">$40</span></li>
</ul>
The user can then TAB to get the price information instead of listening to the product description before getting the price. You should try to only use tabindex="0" for tabbable elements or tabindex="-1" for elements that should not get focus
Example: https://stackblitz.com/edit/angular-fecmdv?file=src/app/app.component.html
Related
I'm having a hard time with a custom dropdown menu I made. I'm trying to make it keyboard accessible, but I'm not having much luck with the listbox option. I'm following the instructions I find under WCAG pages, but I'm not having any luck. Here's one of the dropdowns on my page:
<ul class="custom__options dropdown story-selector" id="storyFilter">
<li class="custom__option selected" data-type="all" tabindex="0">All</li>
<li class="custom__option" data-type="news" tabindex="0">News and media</li>
<li class="custom__option" data-type="analysis" tabindex="0">Analysis</li>
<li class="custom__option" data-type="press" tabindex="0">Press releases</li>
</ul>
Here's a working Codepen to play with.
Your Codepen example uses WAI-ARIA attributes but have missing roles and expected keyboard behaviours.
In order to be accessible, all elements must have a minimum of a role and a name.
Your role sets a promise to the user of what kind of element the thing is and sets an expectation of how that thing will behave. Consider a role of "slider". In that single word, you've conveyed a lot of information to the user as to what that component is and how it would behave.
The name helps the user to understand the purpose of the element. The name of a volume slide would be "Volume".
Related attributes and properties are typically applied to one element, or are implied through coded relationships (using aria-labelledby for example). You would not do the following in HTML, for example:
<span alt="My image's text alternative">
<img src="image.png">
</span>
Yet I see things like this often for ARIA menubar implementations:
<li role="menuitem">
Home
</li>
There are options here, but with similar markup, the following would be more appropriate for the interactive menuitem:
<li role="none">
<button role="menuitem" aria-haspopup="true">Home</button>
</li>
It's best to use HTML elements with the closest semantics to what you are hoping to achieve, hence using the <button> element above. A lot of accessibility comes for free when you take this approach, since browsers add many (or all) of the behaviours expected by the user.
If you were to do the above using <div> and <span> elements, you need to enable appropriate keyboard focus and handle both mouse and keyboard events.
<div role="menuitem" aria-haspopup="true" tabindex="0">Home</div>
The W3C's WAI-ARIA Authoring Practices details approaches and expectations for common design patterns. For example, if you have several top-level items to choose from, you would want to use a Navigation Menubar.
Based on the Codepen example, what you are looking for is probably something like a Menu Button (or this alternative Menu Buttons tutorial), since you only requite a single dropdown menu rather than a whole menubar. This would produce something like the following:
<button aria-expanded="false" aria-haspopup="true">Story type</button>
<div role="menu">
<button role="menuitem">Home</button>
<button role="menuitem">All</button>
<button role="menuitem">News and media</button>
<button role="menuitem">Analysis</button>
<button role="menuitem">Press releases</button>
</div>
I have links that point to sections in the page. To improve accessibility, I have added the attribute role="button" to these as my understanding was that these links are within the page and simply go to a section. But I am not sure if doing this is appropriate.
<ul>
<li><a role="button" href='#section1'>Go to section 1</a></li>
<li><a role="button" href='#section2'>Go to section 2</a></li>
</ul>
<div style="height:15rem"></div>
<h2 id='section1'>Section 1</h2>
<div style="height:15rem"></div>
<h2 id='section2'>Section 2</h2>
No.
You have links, which are functioning as links. That they are linking to another part of the same page doesn't make them buttons.
See WAI-ARIA Authoring Practices 1.1
A button is a widget that enables users to trigger an action or event, such as submitting a form, opening a dialog, canceling an action, or performing a delete operation.
You are doing none of those things.
It also says:
The types of actions performed by buttons are distinctly different from the function of a link (see link pattern). It is important that both the appearance and role of a widget match the function it provides. Nevertheless, elements occasionally have the visual style of a link but perform the action of a button. In such cases, giving the element role button helps assistive technology users understand the function of the element. However, a better solution is to adjust the visual design so it matches the function and ARIA role.
… which highlights that links are a different thing.
What is best practice to enhance the semantic accessibility of a website <nav> landmark with a nested <ul> list for screen reader users? (aria-label and list level are currently not pronounced by all screen readers)
I tested with Voiceover on iOS 9, Talkback on Android 5 and NVDA 2016-1 on Win10 (in Firefox). I used (mostly) default settings in the screen reader applications.
I thought the following list should be optimal prepared for screen reader users:
Demo code 1
<nav>
<ul aria-label="product navigation">
<li>Product A
<ul aria-label="sub menu Product A">
<li>Specifications</li>
<li>Accessories</li>
</ul>
</li>
<li>Product B
<ul aria-label="sub menu Product B">
<li>Specifications</li>
<li>Accessories</li>
</ul>
</li>
</ul>
</nav>
Expected result: Screen reader say something like this:
Beginning of navigation landmark
Beginning list level 1 "product navigation" with two elements
"Product A" link
Beginning list level 2 "sub menu Product A" with two elements
"Specifications" link
"Accessories" link
End of list level 2 "sub menu Product A"
"Product B" link
Beginning list level 2 "sub menu Product B" with two elements
"Specifications" link
"Accessories" link
End of list level 2 "sub menu Product B"
End of list level 1 "product navigation"
End navigation landmark
I also expected detailed info when touching sub menu items on table/phone, e.g.
"Specifications" link level 2 list "sub menu Product B"
But unfortunately this is not working in Voiceover, Talkback or NVDA.
The list labels and the list level are both not spoken.
When using a screen reader and jumping from list to list (like using l key or the list rotator/navigation) you have no idea, what list you're in. In case the elements of the children lists have similar links (like in the demo code) this problem seems for me to be even worse.
I also think it is very confusing (at least for me) to hear "beginning of list" and "end of list" multiple times with no hint, what kind of list is beginning or ending - especially when you are on a mobile or tablet and discovering the display content randomly with your finger.
I made a test series and tried different variations, e.g. I added explicit role="list" and "listitem". I also added aria-level="1" and "2" to the listitems as shown in this example - without success. Are list levels supported by any screen reader software?
One of my findings: At least Voiceover (on iOS) is telling the aria-label of the <ul> elements, but only when defining explicit role="list" like in the following code. But this also only works when the <nav> container is not used - Voiceover (on iOS) is ignoring the fact that there is a list completely when using <ul> within <nav>. So when using a <nav> landmark the list is gone in Voiceover and also not accessible via the rotator/list navigator.
Demo code 2
<ul role="list" aria-label="product navigation">
<li role="listitem">Product A
<ul role="list" aria-label="sub menu Product A">
<li role="listitem">Specifications</li>
<li role="listitem">Accessories</li>
</ul>
</li>
<li role="listitem">Product B
<ul role="list" aria-label="sub menu Product B">
<li role="listitem">Specifications</li>
<li role="listitem">Accessories</li>
</ul>
</li>
</ul>
I think when using a nested list it is important to tell the blind user the nesting level and the list label (at least for the sub level lists, so you know that it is a sub level list) - is there currently a way to solve this?
In case it is not possible, I'd say that it is not a good advice to use nested lists in <nav> for navigation... or nested lists at all?
Edit 1: Updated demo code
Edit 2: More findings
In this answer to another question is made clear, that there are no fixed rules about how screen reader should handle/read aria-label.
<nav> and <ul> are grouping elements - according to the answer the labels are more likely to be read - unfortunately not in my tests when there are nested lists in a navigation landmark.
I also found a page listing some screen reader test results for unordered nested lists - at the beginning they state what "should be announced", so it's optional. :/ The Voiceover results of this page are not valid for Voiceover on iOS 9, the nesting level is not announced in my test.
On the NVDA GitHub issue tracker there are also multiple discussions about the way to implement support for aria-label. And I also found this long but really interessting article about the ridiculous complicated world of aria-label.
Anyway, so now I know I can't expect that nesting levels or aria-labels are announced by default. I'm still wondering if there is a way to enhance accessibility for blind users when the screen reader software doesn't support this functionality...
I know there are some people on Stack Overflow who use screenreader software everyday by necessity, while I only use it for testing. So if any of them contradict my answer, go with their suggestions.
But to me, all the additional ARIA you want to add would just make the menu longer to listen to. The content itself is what makes it clear these are submenus (when there is real content and not example content), so there is no need for aria-label attributes. It's confusing for you, but remember that you only use a screenreader on the sites you build, not every site. Being consistent with the rest of the web's navigation helps people understand your site more quickly.
Also, ARIA roles as in your second example are intended to change the way HTML elements are reported to screenreaders (e.g. A div which behaves like a button). Since you are adding matching roles, you are increasing your workload without adding usability for anyone.
So using semantically correct HTML is all you need to do in this case to make a perfectly accessibile menu. There is no need to add ARIA until you are building unusual widgets, not standard links and text.
You won't help users by giving them the nesting level number, or ask them to remember the menu section they are into.
If you really want to help the users, tell them where they are everywhere.
See https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-link.html
<nav>
<h2>Product navigation</h2>
<ul>
<li>Product A
<ul>
<li>Specifications</li>
<li>Accessories</li>
</ul>
</li>
<li>Product B
<ul>
<li>Specifications</li>
<li>Accessories</li>
</ul>
</li>
</ul>
</nav>
You can use the title attribute conjointly with the aria-label attribute in order to be compatible with the majority of screenreaders and be accessible for non-screenreaders users.
The reason you're not getting the labels read out is because you have them as arial-label instead of aria-label in your code. If you change this to aria-label they will be read as the screenreader is going through the document. If you are tabbing through the links, however, the aria label of the list element will not be read as it's not a focusable element. The screenreader should handle the nesting properly without the need for additional labelling - I've tested this in NVDA and it works as expected - it will announce 'list with two items' when I tab from 'Product A' into "specifications'. Hope this helps.
Recently I've been implementing ARIA into a web application and I found this question to be quite helpful in the improving the navigation parts.
After implementing this in all modules, I discovered this HTML validation error:
Attribute aria-selected not allowed on element a at this point.
Looking at the ARIA specification, I see that aria-selected is only used in roles gridcell, option, row, and tab. In my case, the role of the link is menuitem.
This is a representative sample of the HTML code:
<nav role=navigation>
<ul role=menubar>
<li role=presentation><a href='page1.php' role=menuitem>Page 1</a></li>
<li role=presentation><a href='page2.php' role=menuitem>Page 2</a></li>
<li role=presentation><a href='page3.php' role=menuitem aria-selected=true>Page 3</a></li>
<li role=presentation><a href='page4.php' role=menuitem>Page 4</a></li>
</ul>
</nav>
As you can see, this is taken on "page 3".
What is the correct ARIA role to use here?
you may also use aria-current="page" for describing current displayed page among navigation items.
I believe that aria-selected is for 'widgets' that are one-tab stop, like a set of tabs that you then arrow around to select. The selected aspect is about which one is in focus, not which page you are on.
I would check out this as a well tested example:
http://whatsock.com/tsg/Coding%20Arena/ARIA%20Menus/Horizontal%20(Internal%20Content)/demo.htm
From: http://whatsock.com/tsg/
For showing the current page I would probably use a more traditional method: Make it not a link. E.g:
<li><a href='page2.php'>Page 2</a></li>
<li><strong>Page 3</strong></li>
This also prevents people from clicking on the same-page link by accident (which I see quite often in usability testing). You can apply the same CSS to nav ul a and nav ul strong and then override the styling for the strong.
Short answer: you can use aria-current="page" or aria-current="location" to indicate the current link in a list of links.
Your pagination component could be improved in terms of accessibility (you can see this as a variation of the similar breadcrumbs pattern):
<nav aria-label="pagination">
<ol>
<li>
Page 1
</li>
<li>
Page 2
</li>
<li>
Page 3
</li>
<li>
Page 4
</li>
</ol>
</nav>
A few notes:
Use <nav> to automatically use the navigation landmark (<nav> is equivalent to <div role="navigation"> but shorter and more elegant)
Use aria-label to provide a meaningful name to the <nav> (most likely, you have more <nav> elements on the page and you should label each one accordingly).
Use to make the set of links structured. This can also help screen reader users as it will be announced as "pagination, navigation (next) list, 4 items, helping users understand how many pages there are.
Use aria-current="location"oraria-current="page"` current page of the list (this is most likely shown in a different style as the other pages, but we need to mark it for screen reader users).
I'm currently trying to come up with a good and accessible way to format a status indicator which should be rendered within a set of wizard-like pages on a website. The website should provide a multipage form with a status indicator on top of it as demonstrated in the wireframe below:
Given the new progress-tag in HTML my first thought was to do something like this:
<progress value="2" max="3">
<ul>
<li>Beginning</li>
<li class="now">Right now</li>
<li>End</li>
</ul>
</progress>
... but since <progress> only accepts phrasing content using a list is not really an option. So right now I would probably go with something like this, integratinng the ARIA progressbar-role:
<ul aria-role="progressbar" aria-valuenow="2" aria-valuemin="1" aria-valuemax="3" aria-describedby="state2" aria-valuetext="Right now">
<li id="state1">Beginning</li>
<li id="state2" class="now">Right now</li>
<li id="state3">End</li>
</ul>
But again, I'm not really sure if the progressbar role can be applied in such a way to a list.
Another problem is, that <progress> is rendered as progress bar in Opera, for instance, so >progress> itself is probably not really a viable solution altogether :-(
Can anyone perhaps recommend an accessible status bar that does not only rely on using a single image?
Current solution
For now I will go with following markup:
<section class="progress">
<h1 class="supportive">Your current progress</h1>
<ol>
<li><span class="supportive">Completed step:</span> Login</li>
<li class="now"><span class="supportive">Current step:</span> Right now</li>
<li><span class="supportive">Future step:</span> End</li>
</ol>
</section>
All elements of the class "supportive" will be positioned off-screen. IMO this way we should have a nice compromise of semantic markup (the state succession is in my opinion really an ordered list ;-)) and accessibility thanks to the additional header and status text for each step.
According to whatwg, you're not supposed to assign progressbar role to <ul> elements.
I'd just ditch <ul> and describe progress using (surprise) phrasing content:
<section role="status">
<h2>Task Progress</h2>
<p>You're now at <progress value=2 max=3>"Right now" step</progress>.
</section>
Update: You're right, progress doesn't suit here, it's more like an interactive form widget. I should've checked first, before taking it from your first example. But anyway, the point is there's no need to use a list (even more so, unordered list), when you can just describe what's going on in plain text. In the case that the list of past and future steps is necessary, I'd just add two more paragraphs, one before the status (‘You've completed the "Beginning" step’), and one after (‘Next step will be the "End" step’).
However, I admit that this isn't a complete answer to your question.
Also, I'd say some aria attributes look redundant to me. For example, aria-valuetext perhaps would make more sense in the context of interactive widget, when there's no other human-friendly description of its state. Though I may be wrong here.