I have be rewriting my website to be accessibility friendly and have a really good handle on good behavior, but I'm having a problem with the following pattern:
I have a list page of blog entries that I am trying to remove a duplicate link alert for (I know it's just an alert, but it's right to alert me).
<article>
<a href="destination">
<img src="decorative picture.jpg" alt="">
<h2>Blog entry title</h2>
</a>
<p>Summary of blog post and other meta info about the post</p>
<p>
<a href="destination" class="btn btn-details" tabindex="-1"
aria-label="Continue reading about Blog Entry Title">
Continue reading
</a>
</p>
</article>
The usual pattern discussed is when you have an image and title together (solved), but what should I do with the "continue reading" part? It is not, nor should it be, near the image/title, but it really is redundant. I thought about either making the link or the surrounding paragraph aria-hidden="true" because "Continue reading" is really stylistic, someone in a screen reader would know to click the link above, but I know we're not supposed to put links in a hidden context. I thought tabindex="-1" would solve that problem, but there is still a link there, it's just not focusable and is weird for visual navigators because they can't tab to it.
I found the following article, which makes me wonder if I should remove tabindex and use aria-labeledby to bring some semantic connection to the previous link?
<article>
<a id="md5-hash-of-destination" href="destination">
<img src="decorative picture.jpg" alt="">
<h2>Blog entry title</h2>
</a>
<p>Summary of blog post and other meta info about the post</p>
<p>
<a aria-labeledby="md5-hash-of-destination" href="destination"
class="btn btn-details">
Continue reading
</a>
</p>
</article>
What is the optimal way to "eliminate" the entire Continue reading link to give the best UX to people who use screen readers et al?
I think the key to your question is at the very end where you're asking about the UX since the code you have is technically accessible according to WCAG.
Having two adjacent links go to the same destination isn't ideal but it's not a horrible UX either. Users with mobility issues will have two tab stops to navigate through for each article, which can be draining for some assistive technology such as a sip-and-puff device.
I'm not sure I see the need for the "continue reading" link at all. Hearing the blog title and that it's a link, then a summary afterwards seems sufficient. What benefit is the "continue reading" link? I suppose my question might be better asked on https://ux.stackexchange.com/.
If you have to keep the second link for whatever reason, you definitely don't want tabindex="-1" on the link. That would give you a link that mouse users can click on but keyboard users couldn't. Technically, that's not a failure of WCAG 2.1.1 since that guideline says that all functionality of the page must be available to keyboard users, and since your first link is available, having the second link unavailable doesn't fail.
But if you shouldn't have tabindex="-1" on the link, then you shouldn't have aria-hidden="true" either. As you said, interactive elements should not be aria-hidden.
If you really want to keep the second link, my first choice is just leave it as is. If you only want one link clickable, then perhaps make the entire <article> a link. That would cause the blog title and the blog summary/metadata and the "continue reading" to all be read as the link name. That makes for a pretty wordy link, which isn't a great UX either.
So I'm not sure you have a win-win situation. My first choice is to remove the second link completely. The "continue reading" doesn't seem to have any benefit.
Your second code example is not much different from your first. You changed the label of the second link so it ends up being less accessible than your original code. You'll hear "blog entry title" as the name of both links. The "continue reading" will not be announced because you're overriding the link text with the aria-labelledby.
Related
I have a button which opens a calendar modal, I know calendars are bad for accessibility but my client insists on it. This is the code that opens that calendar modal.
<div class="col-sm-6 hidden-xs text-right calendar-cta">
<a type="button" onclick="openNav()" href="#" class="btn-primary">Calendar view</a>
</div>
I then have a close button on the model, which is where the accessibility error is being produced. The x is showing up as 'Text not included in an ARIA landmark'. What am I doing wrong? What do I need to add in order for this to stop producing the accessibility error. Any help would be hugely appreciated.
<div id="myNav" class="overlay" role="menu">
<a class="closebtn" tabindex="-1" role="menuitem" aria-label="close calendar view">×</a>
<div class="overlay-content"> </div>
</div>
This is more of a warning than an error. It's not required under WCAG, although it is best-practice, and you should try to do it if you can.
It is a best practice to include ALL content on the page in landmarks, so that screen reader users who rely on them to navigate from section to section do not lose track of content.
https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA11
You should ideally be using HTML semantic sectioning elements, like: <main>, <nav>, <aside>, <header>, <footer>, etc. This warning is saying that all rendered content should be in some sort of containing element that has an ARIA role associated with it.
There's a great chart that maps all of the HTML 5 semantic elements to their implied ARIA roles.
I'd also recommend changing your a.closebtn to a button element and removing tabindex="-1". Since you're not navigating to a different location, but rather doing something that causes a change to the UI, I think that a button is a more appropriate choice. The tabindex attribute isn't necessary and only serves to prevent receiving focus by manually tabbing.
The direct and the short answers to the questions:
What is wrong here is that aria-label does not contain the visible text and it is a concrete WCAG failure under 2.5.3 Label in Name. Why and how it fails is explained under Failure due to the accessible name not containing the visible label text
Two quick and dirty solutions:
Write "close calendar view" instead of "x" if possible and remove the aria-label attribute
Hide the "x" sign from ARIA by putting it inside <span aria-hidden="true">x</a>. The one and only thing the screen reader will read will be "link close calendar view".
The "Text not included in an ARIA landmark" may still show up, it is a false positive when it is hidden from ARIA.
However, the above fix will fix only 2.5.3, but there are more important issues here.
I wonder
Why the role="button" was assigned to an anchor element to make a button, when there is the button element readily available and no link to anywhere was intended.
From Bootstrap:
When using button classes on elements that are used to trigger
in-page functionality (like collapsing content), rather than linking
to new pages or sections within the current page, these links should
be given a role="button" to appropriately convey their purpose to
assistive technologies such as screen readers.
What tabindex="-1" does there. It will remove the button from the tab order and the keyboard user will not be able to reach or operate it. It causes a concrete 2.1.1 Keyboard failure.
Why closing the calendar view button has a role="menuitem". Is there a menu there?
Moreover, the usage of the "x" character as the only visible accessible name of a button is a 1.3.3 Sensory Characteristics failure. It is an assumption that all users know "x" denotes "close". Just like not everyone understands an asterisk denotes "required fields", ">" sign means "next", or 3 bars on top of each other is now a menu called "hamburger menu". These should all have some textual explanation. Aria label makes the explanation for the screen reader users but some sighted users may still fail to understand what is meant there.
Alternative code, not including how the btn-close works: (Close button Bootstrap v. 5.0)
(Please note that Bootstrap does not address the 1.3.3 criterion explained above, that is why I included a tooltip in my suggestion.)
<div class="col-sm-6 hidden-xs text-right calendar-cta">
<button type="button" class="btn-primary" onclick="openNav()">Calendar view</button>
</div>
<div id="myNav" class="overlay">
<button type="button" class="btn-close" aria-label="Close calendar view" title="Close"></button>
<div class="overlay-content"> </div>
</div>
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.
This question is about Accessibility.
Here is my code:
<a href="https://example.com/url-to-details">
<img src="https://example.com/item.png" alt="some description">
</a>
some description
It's not perfect, as we know we should avoid Adjacent links go to the same URL (this is what the WAVE accessibility tool says for me on my webpage about this piece of code).
With another words, the problem here is you use th Tab key consequently and still appear on the same link. This is not perfect.
My solution is to set tabindex="-1" for one of the links.
So, my questions are:
1. is it a good idea, or you have a better approach?
2. Which code is better from the Accessibility point of view:
<a href="https://example.com/url-to-details" tabindex="-1">
<img src="https://example.com/item.png" alt="some description">
</a>
some description
or
<a href="https://example.com/url-to-details">
<img src="https://example.com/item.png" alt="some description">
</a>
some description
P.S. There is a 3rd approach: to unite two <a></a><a></a> into one such as <a> picture + some description</a>, but I would avoid it for some reasons.
P.P.S. The description text "some description" is equal for both the image description and the text in the anchor tag.
I don't see a use case for having both an image link and an adjacent textual link that use the same URL. It should be a single link, so you have three options:
get rid of the image link,
get rid of the textual link,
combine the image and the text into a single link, where the image has an empty alt attribute:
<img src="https://example.com/item.png" alt=""> some description
In the third case, the alt attribute should be empty in order to avoid duplication of text (screen reader users don't want to hear the link text twice). This also results in simpler code that does not rely on tabindex="-1". See also WCAG Technique H2: Combining adjacent image and text links for the same resource.
Note that using two adjacent links, both with the href attribute and one of them having tabindex=-1, as proposed in the question, will result in both links being listed in a screen reader's list of links. This duplication should be avoided.
Assuming that your alt description should be equal to your link text is a misguided approach, in my opinion.
Let's say you are designing a products list page for an online store.
If the link goes to a product detail page, then the link text should describe that detail page. However, the image alt should describe the image itself, not the detail page.
.link {
display: flex;
flex-direction: column;
align-items: center;
}
<a class="link" href="https://www.mywebsite.org/detail-page-100">
<img class="link-img" src="https://picsum.photos/200" alt="2 puppies running through a meadow in the summer sun">
<span class="link-desc">Buy organic pet food - 5kg</span>
</a>
The tabindex only changes the keyboard order, but screen reader will still announce the same link twice.
Making the img clickable using javascript will avoid annoying keyboard users or screenreader users, letting mouse users click on the image itself.
From a purely WCAG accessibility point of view, nothing has to change in the original code. That fact that WAVE points it out is just an artifact of that tool. It's not an error, but an "alert" (in WAVE terms). The doc for WAVE says this about "alerts":
The goal should not be to get rid of all icons, except for the errors. Alerts will require close scrutiny - the[y] likely represent an end user issue.
The key being that alerts are "end user" issues, meaning usability or user experience issues. Not accessibility failures.
So, if you're trying to comply to WCAG AA, having a redundant link is not a failure and does not have to be fixed. But if you're looking at the user experience, reducing the number of tab stops and links that point to the same destination is always a good thing.
How you fix that issue seems to be the crux of the OP. When two links that are adjacent point to the same location, the best way is to combine the links into one. Adding tabindex="-1" to one is generally a bad idea because that only affects keyboard users and not screen reader users.
I would keep them both, because if a person using a screen reader is tabbing through your website you would like them to hear the image description as well as the text in the anchor tag.
The correct answer is - it depends.
If your image better describes your link, then use the image.
If your anchor tag better describes it - then use the <a>.
Some info for tabindex
Please see all the accessibility you can add to a link here
I am getting H2 violation for below anchor tags.
It says 'H2: Combining adjacent image and text links for the same resource'
<div class="selected-label ccyImage">
</div>
<a href="javascript:void(0);" class="btn dropdown-html-toggle" tabindex="-1">
<span class="caret"></span>
</a>
But there is no any image used. Not getting how to resolve it.
So you have some unspecified tool which is detecting an accessibility problem which is different to the accessibility problem you actually have (or it is being really smart and noticing that you are expressing content using background images … don't do that).
There's not much you can do about the misidentification of the problem other than to report a bug to whomever makes the tool.
You can make your HTML more accessible by:
Not using links when you aren't linking somewhere. If you're using href="javascript:void(0);" then you're doing something wrong.
Link to somewhere useful and progressively enhance or
Use a button (not a link) if you can't make it work without JS
Putting content in your links (or buttons). There is no text at all there to give any clue to the user what the interactive element is going to do.
I have an image
<img src="sample.jpg" alt="sample">
which is reading as LINK GRAPHIC by JAWS, I have to make JAWS to read as Sample Image.
Why would you try to make JAWS read something in particular?
The important part is the information and content your page is giving to your users. What's the purpose of this content?
Only then, verify that screen readers are reading out the information in a correct manner. a>img is a link graphic; JAWS is correct.
Ryan's Notes
There are two ways to maybe get it like that:
Make sure the user is in expert mode with specific settings. Asking a user to adjust their settings so your site reads nicer, probably won't happen.
Write a JAWS script to interpret <a><img> a certain way. _See #1, _
Wrap your text with invisible content markup and hide img-tag from JAWS via aria-hidden:
<a href="#">
<div style="font-size: 0; line-height: 0;">JAWS reads this text</div>
<img src="sample.jpg" alt="sample" aria-hidden="true">
</a>
More ways to create invisible content can be found here:
https://webaim.org/techniques/css/invisiblecontent/