My company is doing some ADA conformance revision. I need to have the button text read when the user interacts with it. Will that happen with aria-label or .. how do you do it?
The button text should be read when the user navigates to the button. That could be done with the tab or a screen reader shortcut key such as B to go to the next button, and several other ways.
Are you saying you want the button label announced when the user navigates to it and when the user selects it? That sounds like unusual behavior but perhaps it makes sense in the context of your app.
If you want something announced when the button is selected, you can do that with aria-live. You'd have to trick the screen reader into saying it. You can have a visually hidden element such as
<div id="foo" aria-live="polite" class="sr-only"></div>
(Note: See What is sr-only in Bootstrap 3? for info on the "sr-only" class.)
When the button is selected, inject the text you want announced into the <div> and it'll be read.
A Screen Reader will announce the title of the button when it comes into tab focus, and let the user know that it's a button to begin with. As a base requirement though, a native <button> element should be used since the functionality is already built in. With that said, you don't need any other particular aria tags by default.
I'm guessing you just want to know how to mark up a button so that JAWS says its text when the user tabs or cursors to it.
If it's a native button with text written on it:
<button>Next</button>
JAWS will read it automatically.
If it's an input:button with a text value:
<input type="button" value="Next" />
again, JAWS will speak its text automatically.
If it's a button with an icon:
<button><span class="fas fa-arrowRight"></span></button>
mark it up like this and JAWS will speak its name (remember to change the aria-label text if you're using a different language):
<button aria-label="Next"><span aria-hidden="true" class="fas fa-arrowRight"></span></button>
Hope this helps.
Related
<div role="button" aria-label="Open" tabindex="0">
<span title="open file">go to file</span>
</div>
My screen reader is reading open button.
But I want it to read open button go to file.
How I can achieve this? Thanks in advance.
aria-label overrides all text that might be contained in child DOM nodes. See https://www.w3.org/TR/using-aria/#label-support, in particular the third last bullet point:
Don't use aria-label or aria-labelledby on a span or div unless its given a role. When aria-label or aria-labelledby are on interactive roles (such as a link or button) or an img role, they override the contents of the div or span. Other roles besides Landmarks (discussed above) are ignored.
If you literally want "open" read before the role, "button", and then have "go to file" read afterwards, you're talking about having a "description" for your element, but I suspect forcing that reading order will cause a WCAG 2.5.3 Label in Name issue, which I'll explain shortly.
But first, here's how you would get that order:
<div role="button" aria-label="Open" tabindex="0" aria-describedby="newid">
<span title="open file" id="newid">go to file</span>
</div>
Add aria-describedby to the button and reference the ID for the <span> (and add an ID to the <span>).
Most screen readers will read the label of the element first, then the role, then the description, but that's not guaranteed. You'd have to test with NVDA, JAWS, and Voiceover (on the Mac and iOS).
Now, the problem with WCAG 2.5.3 is that you now have a button that displays "go to file" as the label of the button but the name (accessible name) of the button is "open". This means that a speech interface user (such as Dragon Naturally Speaking) will have to say "click open" in order to select the button but the word "open" is not displayed anywhere on the button. All the user will see is "go to file" on the button so they're going to think they can say "click go to file". But since "go to file" is the description of the button and not the name, it won't work.
So you can do what you're originally asking for but it makes a pretty severe accessibility issue.
You might want both "open" and "go to file" in the accessible name of the button and not use a description, but that means you'll hear "open, go to file, button", which is not the order that you originally requested.
ARIA: button role
đ This May Help
I have a custom component in angular that handles images. I have alt text as an input to the element and the screen reader picks it up to utter it out. But whenever I tab to the image, it says 'Trash' group. I want the screen reader to read it out as 'Trash' button. How can I achieve this? The following is my current implementation:
Icn component:
<img [ngClass]="class" [file]="file" [alt]="alt">
Usage:
<icn class="del-icon" [file]="'trash'" [alt]="Trash"></icn>
I tried role="button" but that didn't work.
I don't know Angular so you may need to do some digging on how to structure this but your approach is making things difficult.
Instead make the button a <button>. This way you get all the native accessibility built in (e.g. accessible via tab by default, accepts focus, has hover and focus states etc.)and you will also get the correct announcements in screen readers.
Then place the icon inside the <button> and just style it appropriately.
<button> <!--add whatever directives angular requires here-->
<img [ngClass]="class" [file]="file" [alt]="alt">
</button>
Also you may consider using inline SVGs for your icons as they offer styling options and can change colour according to user preferences. It is also one less resource to download so will help with performance.
I figured out the solution to this problem by experimenting more with the roles.
The image tag doesn't take the role="button" as an attribute. Instead, the role needs to be assigned to the parent element of the image tag i.e., in my case the component icn like follows:
<icn class="del-icon" role="button" [file]="'trash'" [alt]="Trash"></icn>
Now, the screen reader software reads out as the 'Trash button' and gives further more instructions on how to interact with the button. And also if the above doesn't work, just by encapsulating the custom component in a span tag and assigning the role="button" to the span tag works like a charm.
<span class="del-btn-container" role="button">
<icn class="del-icon" [file]="'trash'" [alt]="Trash"></icn>
</span>
Note: Button role examples
I am trying to make my web application more accessible and one of the things I want to do it create a role group and the contents inside should be read in a particular fashion.
For ex on the UI it looks like a menu bar
TITLE
Button1 Button2 Button3
The html looks like
<div class="tab-content-header" role="menubar">
<span id="{{label}}">{{label}}</span>
<button type="button" class="btn btn-primary">button1</button>
<button type="button" class="btn btn-primary">button2</button>
</div>
I want the screen reader to focus on the button ONLY and read 'button1 button, title" and "button2 button, title". Right now it doesnt read that way. any idea?
Before I answer your question, note that you are using a role="menubar" but none of the items within contain role="menuitem". I recommend you read through the menu bar pattern in the ARIA Authoring Practices 1.1, as it also defines the keyboard actions you will need to implement. Further, in most cases using ARIA to define menus is a way of telling a user that it will behave just like a system menu bar. If you do not match the necessary interactions then you will confuse users.
Now, a screen reader will announce the accessible name of a <button> as the text within the element: <button>Accessible Name</button>
If you want it to announce some additional text, you can use aria-describedby, though it will be announced after a pause.
So this may get you what you want:
<span id="Desc">Description text</span>
<button aria-describedby="Desc">Button Text</button>
Now, you state that you want something to be read in a particular order, and that you want only the button to be read, and your question says you want a role name read. These are all confusing requirements so I am not sure I addressed your goal.
All that being said, please be careful to assert how a screen reader user should experience your content. Often using ARIA to enforce the author's ideal reading order makes a page more inaccessible than if nothing was done at all. So please be certain to test with real users.
I have a split button construct in our applications that is similar to the following jsbin.
http://jsbin.com/opAtiYEl/8
The first button would do a default action and the second button would give a menu (ul) with more related actions.
When i tab into the first button it reads "action button". That's fine. But when i tab into the arrow down button it reads "button".
What is the correct approach to make this work accessibly? I'm thinking aria-haspopup but that doesn't read on Voice Over.
Ideally this should be correct for VOice Over, NVDA and Jaws (latest minus 2). I'm trying to find a good baseline here or suggestion?
You are some what on the right track with aria-haspopup.
And as #Menelion ElensĂșle said your arrow button has no content.
Let's say we do something like the iTunes store and have 1 link to a category and a dropdown for sub-categories...
This is the proper markup
Movies
<button type="button" class="action-dropdown hide" aria-haspopup="true" aria-expanded="false" aria-controls="movies-menu">movies dropdown</button>
<ul id="movies-dropdown">
<li>Adventure</li>
...
</ul>
Use the class "hide" to visually hide the text. (Don't use display:none)
And when the arrow is clicked change aria-expanded to true, and remember to switch it back to false when the dropdown is hidden.
My JAWS 15 says "Unlabeled 3 button". You have to label your button. Here:
<button>Action</button>
<button class="arrow"></button>
Please note: the second button has nothing between the tags. If it's impossible to insert something in there (it would corrupt your design), then it would be appropriate to make your arrow as a plain image with an alt attribute.
In my AngularJS project I have an account details page where you can change your personal account information. This page allows for multiple phone numbers and e-mailaddresses to be supplied. Using mouse input (or tabbing to buttons and pressing them with space bar) works perfectly, however I'd like to add the convenience of the enter key pressing the 'logical' buttons.
My form looks like (accidentally forgot to translate a few items):
A simplified version of the HTML for the form can be found on PasteBin, I've mainly removed the directives for managing the lists.
All buttons are <button> elements except for the cancel button which an <a> to the previous page, and the submit button is <button type="submit">.
When selecting any text box and pressing enter, the first (non-disabled) <button> element is 'clicked'. Meaning if I would change the last name, hit enter, the first phone number would be removed.
When you're in a new entry of phone numbers or e-mailaddresses (the row with the green + button) it should click that button, and if it's disabled do nothing.
When you're in any other text box on the form it should hit the save button, and also if the save button's disabled, do nothing.
Both buttons will be disabled based on form validation.
There'd be no trouble in changing the type of a button from button to submit if that'd help.
I would preferably have an all HTML solution, using just semantics, but I doubt that's really possible. So the logical alternative would be to use an AngularJS directive.
Please do not provide a jQuery or plain JavaScript solution relying on IDs or something like that. I don't want to hack my way around AngularJS, rather embrace it.
In the meantime I've worked on a directive that allows me to declare what I've called 'submit scopes'.
In essence you have actions (inputs) and targets (buttons), they're bound through a service by a key you can assign in the template. To avoid keys from clashing and from simple annoying work you can create a submit-scope which will cause it's children to prepend a unique key to the value they're accessing.
Within a submit-scope you can still override an action to use a global key instead by setting the attribute global-submit="true".
Example code:
<div submit-scope>
<input type="text" submit-action />
<button type="button" submit-target>Pressing enter in the above field will click this button.</button>
</div>
You can view the entire source code and a slightly larger example on Plnkr.
I just tried to replace
<button>Cancel</button>
with
<input type="button" value="Cancel">
and it seems to work correctly...