Only screen-reading a child element when it is highlighted - html

I have an element roughly like this:
<a class="parent" tabindex="0">
<span class="info">One line of data.</span>
<span class="info">Another line of data.</span>
<button class="action">Click here to do stuff.</button>
</a>
Because of reasons, I have a link that takes users to a certain page, and inside that link is a button that does something related to the link, but functionally different. When I tab over the parent link with a screen reader, it reads the text of everything inside - both info spans and the button, which is not the behavior I'm looking for. What I want to happen is:
If a user tabs to the parent link, it reads off the contents of the two info spans, but not the button, as this would mislead users about what the link does.
If a user tabs specifically to the button, the contents of the button is read off.
I tried assembling a custom aria-label for the parent link to do what I want, but it proved to be very difficult because some of the content I want to be read is interpolated HTML, which doesn't go very easily into an English string. Is there an easier way of doing what I want to do?

Related

HTML button only redirect when clicking the text inside

Was wondering why when I clicked my button in html it wasn't responding later found out that it will only respond and redirect when I clicked the wording inside "Get Started" was wondering why. This is the code I'm using
<div class="main">
<div class="main__container">
<div class="main__content">
<h1>RAID 2 EARN</h1>
<h2>TECHNOLOGY</h2>
<p>We make it easy!</p>
<button class="main__btn">Get Started</button>
</div>
<div class="imgmain">
<img id="main__img" src="/IMGS/picture1.svg"/>
</div>
</div>
</div>
It is because you're actually clicking the anchor tag inside of the button and the button click doesn't have any actions associated with it. The size of the hyperlink is always only the size of its content. You should change your CSS to style your hyperlink to look like a button. Typically, you can do something like this:
<a class="main__btn" href="raid2earn.html">Get Started</a>
This way you're HTML spec compliant and your hyperlink is styled to look like a button but you're using default browser patterns to complete your action.
Your anchor tag is enclosing only the 'Get Started' text instead of the button. This way, only the text becomes a link
Actually, every html element has a job.
<a> for connecting to outer files
<button> for the inside actions
And you can style everyone as you want.
But:
if you still need to use the button and put the a inside and need to be able to click the button and do the action of the a, there are many many ways, some in html, some in css, and others in javascript.
In html, the easiest solution to your issue is to flip the elements, and make the a outside the button like that:
<a href="#">
<button>Click the button now</button>
</a>
This one is just the easiest.
And there are many others in html and css and javascript.
But again, you must use every element in its own purpose.
Sure you are putting a link tag inside a button because you want a button look and feel. just style your a element the way you want your button to look like as suggested above.
Cheers

VoiceOver focuses on aria-hidden element

On our (Vue.js v.2) webpage we have a section where you can swipe between cards, or by pressing "left" and "right" button. This swiping section is written with vanilla JS, and no fancy library. In order to have the adjacent visible when swiping, I need to have all of them visible in the DOM tree, but hiding them from the viewer. I have made it so all the unfocused cards are aria-hidden, and it works great when using ChromeVox. The problem is that when using VoiceOver, and I click the "right" button, and immediately tab down to the card, it will read out the card to the left, and also get trapped there since the card is aria-hidden. Code-wise the change from aria-visible to aria-hidden happens as soon as the button is pressed, but it seems like VoiceOver has already decided that when I am focusing on the "right" button, that the next element should be card 5 (for instance). If I wait around 1 or 2 seconds after clicking the "right" button, it will change the "next" element, and focus on the correct one (card 6) when I tab down. Is there any way to get around this, so it will focus only on the aria-visible element? Maybe a way to "force refresh" VoiceOver's stack of elements to read next? Maybe if I remove the message being read out when clicking the button, it will refresh immediately? I still haven't found of doing either of those things. I created a low quality flowchart to illustrate the problem better. What I want is for it to behave like ChromeVox.
I have tried several methods of getting this to work now, and it feels like it's a bug with VoiceOver. Some of the (desperate) attempts I've tried: setting tabindex=-1, role=presentation, changing the ID of "right" button dynamically as I navigate between cards, creating an empty div with a dynamic ID below the button, using aria-flowto, dynamically setting aria-describedby on the "next" element, and different variations between these and some other stuff I can't remember.
Eventually I found a solution that kinda works. I'm not very happy about it, but it's better than nothing. What I did was to make the title inside the card aria-hidden, and creating a currentHeader variable in store. I created an sr-only & aria-visible title above the swiping section, where the v-html points to the currentHeader variable. This way, the "next" element for the "right" button will always be the same element, but content will change after I click the button. It's not a perfect solution, and for some reason it makes VoiceOver "halt" when trying to go to the next element immediately after clicking the button, but at least the user won't read the wrong text and get trapped. Here's a pseudocode illustration of how I did it if my explaination was confusing:
// old solution // old swiping-section
<button id="left" /> <div v-for="element in elements" />
<button id="right" /> <h3 v-html="element.title" />
<swiping-section /> <p v-html="element.desc" />
</div>
// new solution // new swiping section
<button id="left" /> <div v-for="element in elements" />
<button id="right" /> <h3 aria-hidden="true" "v-html="element.title" />
<h3 class="sr-only" v-html="currentHeader" /> <p v-html="element.desc" />
<swiping-section /> </div>
If anyone finds a better way to do it, please post your solution.

What should be the aria-role for the box that can be opened by clicking on notification icon on navbar?

I am trying to implement the notification component that will show the list of the items and will be opened by clicking on the notification icon on the fixed navigation bar on the top. I don't think it's a menu bar. Because the menu provides the actions that can be performed and it can also have a sub-menu.
https://www.w3.org/TR/wai-aria-practices/#menu
Can anyone let me know what should be the aria-role of such kind of components?
Below is the code sample. I will open the template dynamically by clicking on the notification icon button:-
<button aria-label="notifications">
<mat-icon class="mr-md">notifications</mat-icon>
</button>
<!-- Notification template -->
<div class="notifications__item">
Notifications
<li *ngFor="let notification of notifications" class="notifications__item">
<mat-icon class="notifications__icon material-icons-round">
{{ notification.icon }}
</mat-icon>
<div class="notifications__content">
<div [ngClass]="{ 'notifications__warn': notification?.type }">
<span>{{ notification.title }}</span>
</div>
<div>{{ notification.description }}</div>
</div>
<small class="notifications__caption">
{{ notification.duration }}
</small>
</li>
</div>
There are still a lot of things to consider that your example doesn't cover, so this isn't a complete answer, it is just pointing you to the relevant WAI-ARIA depending on what route you take.
The button
The first thing to consider is the button. You need to tell screen reader users what state it is currently in. For this we use aria-expanded to indicate whether the item it controls is currently opened or closed. (aria-expanded="true" for open, aria-expanded="false" for closed.)
At the same time we want to indicate what item this button controls (as the notification list isn't 'owned' by the element - for example if it was an <li> with a nested <ul> in a menu then the list would be 'owned' by it).
For this we would use aria-controls or aria-owns and point it to the ID of the element it controls. For the difference between them see this stack overflow post as a good explanation, in this example I would say it is aria-controls but yet again depends on your implementation and positioning in the DOM.
With regards to the button itself and where it sits in your menu, this is still considered navigation so it should sit within your <nav> element. However if this sits outside of your navigation along with say a 'help' and 'account' section you may consider those items part of a toolbar. (yet again I would say it doesn't apply here but something to look at)
Also it doesn't appear to be applicable here but if you include any links etc. within the 'popup' / modal that shows the notification list (i.e. a 'view all notifications' link), you should consider aria-haspopup="true"
The notification list
Right so we have a button pointed to the container (don't forget to give the container the relevant ID for aria-owns or aria-controls). Next what about the container itself?
Well in this example it appears that the container should be treated like a modal.
So for this reason you need to consider:-
trapping focus in the modal,
close with Escape,
returning focus to the button that activated it on close,
providing a close button that is accessible by keyboard,
a title for the modal (even if it is visually hidden)
What I would recommend is add some of the accessibility features above, try it with a screen reader and keyboard and see if it is easy to use. Once you have decided on your pattern ask some more questions on specific use case issues as the above is general guidance.
A few things to consider based on your markup
Additional things to consider from your example:-
use aria-hidden="true" on your icons, they don't add anything for screen readers (assuming your notification.title is descriptive).
For the notification title consider making it a relevant heading (<h2> - <h6> depending on position in document.
Don't forget to add some visually-hidden text that describes the warning level (I can see you have some form of colouring / distinction in [ngClass]="{ 'notifications__warn': notification?.type }" - expose the same info to screen readers.)
You currently have a <li> within a <div> - maybe change the outer <div> into an <ul> so it is semantically correct (<div class="notifications__item"> into <ul class="notifications__item">)
I hope the above is useful to set you on the right track, a lot to read but after reading the linked articles you should be able to make a better decision on what pattern you are using (as I didn't even mention making this a sub item within your menu) and can then ask some more questions on specific details you don't yet understand.
final thoughts / tips
test with a screen reader - this is the biggest tip I can give on working out how WAI-ARIA works and interacts with things.
Also if you are ever in doubt as to whether a WAI-ARIA attributre is applicable it is better to not include it.
Incorrect use or WAI-ARIA is actually worse than not including it at all so make sure you understand when to use an attribute reasonably well before implementing it. If I am ever unsure (as it still happens to me!) I tend to look at 2 or 3 examples of it in use and see if my pattern fits the examples I looked at.

508/Accessibility Rules for (1) Links Must Have Discernible Text, (2) Empty Table Cells (Axe Plugin)

I'm running the Axe plugin to ensure the validity and 508 accessibility of my app, and some of the violations reported are too restrictive and I don't know how to fix them because they are valid cases:
1. "Links must have discernible text"
In reference to a Tooltip link which isn't supposed to have any text. It's a graphic and must exist on the page by itself. In general, how do you handle textless links which are very common?
<a href="#" rel="tooltip" data-toggle="tooltip" title="" data-original-title="This is a tooltip icon by itself">
2. All th elements and elements with role=columnheader/rowheader must have data cells they describe
"We are not sure this is an issue, because:
Table data cells are missing or empty"
I have a table where the last column is "Actions" that only contains graphic icons, no text; e.g. there's a View button, Edit button, and Delete button. The column is structured as
<table>
<tr>
<td>
<a href="javascript:void(0)" title="Edit">
<i class="fa fa-pencil" alt="Edit"></i>
</a>
<a href="javascript:void(0)" title="Delete">
<i class="fa fa-trash" alt="Delete"></i>
</a>
</td>
It's the lack of inner-HTML text that triggers Axe's "Empty Cell" violation. Do I just ignore it? This is a common scenario, I don't want to be hit by it constantly.
If your icons, graphics, buttons, or links execute some action you need to provide some text alternative to screen readers that describes the action taken by the link.
Either add an aria-label attribute to the links describing their purpose, or place a span tag with descriptive text within the link that is hidden from sight using CSS but will be accessible to screen readers.
Additionally your usage of the alt attribute on your i elements is incorrect. You should hide the icon using aria-hidden="true", and provide a text alternative via another element.
There is nothing inherently wrong with having an empty td element within a table as the td element has the roll of cell and elements of the roll cell do not require an accessible name. If the cell contains content such as an icon you would want to make sure that an accessible alternative is provided, or if the content is strictly decorative appropriate action is taken.
https://www.w3.org/TR/wai-aria-1.1/#cell
An issue would arise if you had an empty th element as it would have a role of either rowheader or columnheader, and an accessible name is required for both.
https://www.w3.org/TR/wai-aria-1.1/#columnheader
https://www.w3.org/TR/wai-aria-1.1/#rowheader
Helpful information for using icons: https://www.w3.org/WAI/GL/wiki/Icon_Font_with_an_On-Screen_Text_Alternative
Information on describing the purpose of a link: https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-refs.html#navigation-mechanisms-refs-techniques-head
Hiding content from sighted users:
https://webaim.org/techniques/css/invisiblecontent/

What's the point of using anchor in <a id='top'>Top of page</a>?

The first Google search result for "html links" says (paraphrased) that to create a bookmark / section inside a webpage, we've to do this:
<a id='section-2'>Section 2</a>
so that we can link to it like this:
<a href='page.php#section-2' >Click</a>
But why the site is recommending using anchor tag around "Section 2"? -When it can be done using span:
<span id='section-2'>Section 2</span>
Are there compatibility issues? Because the first search result for "creating bookmarks within a webpage" also says to surround the heading with anchor tag:
<p><a name="title">Title</p>
Though this particular example is incorrect for various other reasons.
I've a supplementary question:
Why to surround the heading with the container when it can be done simply like this:
<span id='section-2'></span>Section 2
Does it matter?
<span id='section-2'>Sec</span>tion 2
<a href='page.php#section-2' >Click</a>
There is no point. W3schools is unreliable, just don’t use it, and you will avoid confusion and wrong information; see http://w3fools.com
In the old days, the only way to set a destination anchor within a page was to use <a name=...>...</a> element (at the text level). Later, the id attribute was added and is now supported by all browsers in use, so you can make any element a destination anchor simply by attaching an id attribute to it. E.g., to make it possible to link to a heading like <h2>Section 2</h3>, you could make it just <h2 id=section-2>Section 2</h2>. No need for an artificial extra element.
Using <span id='section-2'></span>Section 2, though formally correct, is not a good idea. You win nothing by using it, as opposite to the more logical markup. And if you e.g. later want to style (highlight) the element to which the user has “jumped” into with a link, using the :target pseudo-class, you will find yourself in an awkward position: the pseudo-class would let you style just the empty content of the span.
Regarding the question in the title, there is no reason to make the top of a page an destination anchror, with <a id='top'>Top of page</a> or otherwise. First, you can refer to the start of the page using just href=# since by URL specifications, # denotes the start of the current resource. Second, “Back to top” links are basically useless or worse: every browser has a simple command for going to the start of the page, and an explicit “Back to top” link can be confusing: back to top of what?
In the early days of html an anchor element was the only way to do this, but just because you can now do it with other element types doesn't mean you should: using an anchor for this purpose is semantically correct because it makes it clear to anybody reading or maintaining your markup that the element is intended as a navigation target. (Noting that there will often be many elements on the page that have an id but are not navigation targets.)
"Why to surround the heading with the container when it can be done simply like this:
<span id='section-2'></span>Section 2
Because if you put the text of your heading inside an element you can style it and/or easily mess with it from JavaScript. Indeed, if it is a heading you may want to put it in an <h1>, <h2>, etc. tag rather than a <span>.