iOS voiceover in web view creates Shadow Content (User Agent) - html

When I turn on voiceover and focus over the image I see "Shadow Content (User Agent)" appear in the dom and voice over will read out a few more divs inside of that shadow dom. I've tried adding aria-label on both the img and the outer class, but it still reads the contents in the shadow dom. A work around I am doing is adding attribute "role=banner" since it is a logo and fits the banner description under wai-aria recommendations.
Does anyone know how to fix this or is this expected behavior for Safari?
<div class="org-logo">
<img class="org-logo__image" src="assets/images/logo.svg" alt="Logo">
> Shadow Content (User Agent)
</img>
</div>

Related

Android Talkback reads text visually positioned above input aloud

I am trying to optimize a few components for screen readers, however Android Talkback proves to be a challenge....
Here is a very simplified example for the code:
<div class="wrapper">
<form>
<span role="presentation" aria-hidden="true">
This should not be read by Talkback
</span>
<input aria-label="This should be read by Talkback" />
</form>
</div>
The text inside the span is updated dynamically, and is positioned absolutely over the input - just to appear like an animated placeholder, without actually being read by screen readers. That is what the aria-label is for. However, TalkBack still seems to recognize the span - so it reads the content of the aria-label first, then continues reading the text in the span... role "presentation" or role "none" did not prevent this, neither did moving the text even further from the input. (For example, outside the form). Is there any way to prevent this?
The role attribute only changes the type of element that Talkback and other screen readers announce. Setting it to presentation or none just removes the semantic type of element. A <span> does not have a native role by default so it's essentially presentation/none implicitly and won't have any effect.
aria-hidden is the key. It will hide the element from the screen reader. (CSS display:none and visibility:hidden will also hide an element from the screen reader but it also makes the element invisible to sighted users too.)
Your code example should work just fine with Talkback. However, you mentioned that you dynamically change the contents of the <span>. That's not a problem but is there a chance that when you updated the text, the aria-hidden got removed?
I have used aria-hidden on Android without any trouble.
The solution in my example was already enough to fix the issue.
aria-hidden prevents the span being focusable, and if the span is located before (and not after), TalkBack will not interpret the text as being part of the input.

How to make mdGridTile's into links

I have a similar question as this thread, but the answer doesn't seem to be listed anymore. I have a list of tiles that show a property image and some relevant information. I'd like each to be a full link to another page with more information on the property.
I've made my tiles into a directive, and currently the html content of that directive is wrapped in an anchor tag. Which works to reach my specified link, however that anchor tag only matches the height of the mdGridTileFooter.
Is there a way to make the entire tile clickable? So that the user can click on any part of it and access the intended link (not just the bottom footer?
The HTML Directive:
<a ng-click="spVm.linkToProperty(proforma)" ng-href="{{spVm.path}}">
<div>
<md-grid-tile-footer class="saved-prop-address">
<div class="saved-prop-address-title" ng-bind="spVm.city"></div>
<div class="saved-prop-address-subtitle"
ng-bind="proforma.listing.update_date | date: 'MMMM dd'"></div>
</md-grid-tile-footer>
</div>
</a>
The HTML Page with the Tile List:
<md-grid-list md-cols-xs="2"
md-cols-sm="3" md-cols-md="3" md-cols-gt-md="6"
md-row-height="1:1" md-gutter="4px">
<md-grid-tile class="saved-prop"
ng-repeat="proforma in sdVm.pageGroups[sdVm.saved.idx]"
ng-click="sdVm.showSelectedProperty(proforma); sdVm.linkToProperty(proforma)"
ng-href="{{sdVm.path}}"
ng-style="{'background-image':'url({{proforma.thumbnail_url}})'}">
<pgo-saved-property proforma="proforma">
</pgo-saved-property>
</md-grid-tile>
</md-grid-list>
Thank you!
Since it looks like the directive had no height, adding any responsive height/width styling to the anchor tag won't work.
Adding this code to the css for the directive, and the anchor tag, will bring the anchor/link to the full height and width of the tile.
style="display:block;height:100%;width:100%;"
And any responsive changes that occur with the tiles will work with this code as well.

Correct way to mark HTML text as decorative with ARIA

In an earlier version of the http://getbootstrap.com/components/#pagination page/section, it had the code:
<nav>
<ul class="pager">
<li class="previous"><span role="presentation">←</span> Older</li>
...
</ul>
</nav>
This has been changed to:
<nav>
<ul class="pager">
<li class="previous"><span aria-hidden="true">←</span> Older</li>
...
</ul>
</nav>
The left arrow (←) is purely decorative, and doesn't need to be announced by a screen reader. According to http://www.w3.org/TR/wai-aria/roles#presentation:
presentation (role)
Example use cases:
An element whose content is completely presentational (like a spacer image, decorative graphic, or clearing element);
An image that is in a container with the img role and where the full text alternative is available and is marked up with aria-labelledby and (if needed) aria-describedby;
...
Whereas:
aria-hidden (state)
Indicates that the element and all of its descendants are not visible
or perceivable to any user as implemented by the author.
I understand that 'role=presentation' is really talking about the semantic meaning of the element, but it seems like the left arrow is directly analogous to 'a spacer image, decorative graphic, or clearing element', and is certainly 'visible or perceivable to any user'.
What's the correct design pattern here? Is the meaning of 'aria-hidden' changing to allow for this specific limitation of 'role=presentation'?
The role attribute is used to override the default mapping of the role of the HTML element to the accessibility tree. This has no effect on the text content of the element.
For example, role="button" on a div will allow the div to be announced as a button but will not change the fact that the text of the div (e.g. "Submit") will still be announced as the accessible name.
In ARIA 1.1 the presentation role has been given a synonym of "none" to better represent its semantic http://www.w3.org/TR/wai-aria-1.1/#none
The attribute aria-hidden is used to hide the element itself and the content (accessible name) of the element from the accessibility tree while keeping it visible in the document. This semantic has always been the case. It has not changed.
unobf is correct but sometimes it helps if you think of what the screen reader user will experience. Consider this simple example:
<div role='button' tabindex=0>alpha</div>
<br>
<div role='presentation' tabindex=0>beta</div>
<br>
<div role='button' tabindex=0>gamma</div>
<br>
<div role='button' tabindex=0 aria-hidden='true'>delta</div>
<br>
<div role='button' tabindex=0>epsilon</div>
If you're using VoiceOver or the virtual PC cursor in JAWS, both will allow you to put your focus on the role='presentation' item and will not state a role but it will say 'beta'. (I like the new role='none' that unobf points out in the 1.1 spec. It makes it clearer that the screen reader should not state any role when it's set to 'none'. As the spec says, it was a little confusing using 'presentation'.) So the presentation item isn't really hidden to the screen reader. You're just telling the screen reader that it doesn't have a role.
Aria-hidden, on the other hand, completely removes it from the screen reader, except in my poor example (which is intentional). If you're using VoiceOver or the virtual PC cursor in JAWS, both will skip the aria-hidden button. The screen reader user won't know it's there. But if the JAWS user is TABBING through the page, they will land on the aria-hidden button because it's a tab stop. But since it's aria-hidden, JAWS gets a little confused on what to say. When I tried it (FF 38 and JAWS 16), it said 'beta', which is the text from a previous <div>. In general, you don't want to aria hide something but make it keyboard accessible. That's just a weird scenario.
Going back to bootstrap's old example, since they used role='presentation' and it's a <span> tag, the VoiceOver and virtual PC cursor JAWS user will both be able to put their focus on the <span> element, which is probably not what they intended. Since the arrow is just for decoration, it makes sense to aria hide it.

iOS Accessibility Voiceover Reads Out Unnecessary Content in Web

My iPhone application is built using Cordova and it for the most part native and I am having an issue with Accessibility. During my accessibility testing I noticed that when Voice Over is selected on some elements it reads out more than just the text of the label or button. For instance here is what a pages header looks like in my HTML:
<div data-role="header">
<div class="page-header">
<h1 class="header-title"><%= title %></h1>
</div>
</div>
When H1 is selected the following is read out to the user:
Banner Title Heading Level 1 Landmark
Is there any way to restrict it to only speak out the title content?
Looks like you are using jQuery Mobile. jQuery mobile adds some markup to the elements based on where you have placed them and the attributes applied. In this case it is placing role="banner" on the div with the data-role="header".
The way that is being read out is fine. If you are in fact using the header as a header, then the screen reader user now has that useful piece of information. If they do not want it, they can tell their screen reader to suppress it. Think of it as the audio equivalent of the fact that the header is visually distinct from the rest of the page.

tabindex or focus for keyboard navigation

I am doing a lot of work with accessibility and WCAG at the moment but one thing I am trying to get to work well for all users and especially those using keyboard navigation, is a skip to content link.
This sounds simple to do, throw a link to an anchor in the top of the page and people can 'click' it to skip navigation or other largely unimportant content.
The issue is, though, when you 'click' an anchor link using your keyboard and then hit the 'tab' key again, you get taken to the element directly after the 'skip to content' link and not the next element in the main content area. Ie, the anchor you linked to has not received focus.
It seems that this is a common problem, because I am yet to find a site with a 'skip to content' link that has this working correctly. Even the Vision Australia site has this problem.
I was hoping that somebody knew of a technique/hack/library to make this work as it should.
EDIT: I can confirm that this issue occurs in Chrome and Safari, but not Firefox on my mac.
Most browsers scroll down visually to the target of the same-page link, but don't actually place keyboard focus on that link. You can use JavaScript (or JQuery, as in the example below) to give focus to the target:
$("a[href^='#']").not("a[href]='#'").click(function() {
$("#"+$(this).attr("href").slice(1)+"").focus();
});
However, there's a bug in WebKit that prevents even this solution from working in WebKit browsers such as Chrome and Safari. I wrote a blog post on this about a year ago, and several others have built on it:
Terrill Thompson blog post
More from Damon Muma
A JavaScript-only solution by Zegnat
WebKit Bug Report
Chromium Bub Report
You may place an another element just above the content you want to receive the next focus. Then skip to that element and hide that from view using diff ways like, font-size 0 or a p tag with no content etc.
<div class="skip-nav-container">
<a class="skip-to-main-content" href="#mainContent">Skip to main content</a>
</div>
<nav>
<!--skip this content-->
</nav>
<div class="skip-nav-target">
<p class="skip-nav-target-content" id="mainContent"></p>
</div>
<main>
<!--next element in the main content area-->
<!--main content-->
</main>