I am addressing the challenge of tabbing through cards that provide project information with links: one to a live demo, and one to the projects Github Repo. I am wondering what would be best practice to navigate through a list of cards without a) too many tab-stops, and b) the visually disabled user from having to think about how to navigate the information between these stops. I do not want to involve JavaScript if possible.
Also, I do use a screen reader (NVDA) to test the functionality.
Here is the basic code I currently have with two list elements for sake of visual look of the code, without class names intentionally:
<ul>
<li tabindex="0">
<h3>Project Name</h3>
<img src="https://via.placeholder.com/744.png" alt="Preview Image of X project">
<div>
<p>
Project Description
</p>
<div>
<a href="{Link to live page}" target="_blank" tabindex="-1">View Demo</a>
<a href="{Link to Github Repo}" target="_blank" tabindex="-1">View Code</a>
</div>
</div>
</li>
<li tabindex="0">
<h3>Project Name</h3>
<img src="https://via.placeholder.com/744.png" alt="Preview Image of X project">
<div>
<p>
Project Description
</p>
<div>
<a href="{Link to live page}" target="_blank" tabindex="-1">View Demo</a>
<a href="{Link to Github Repo}" target="_blank" tabindex="-1">View Code</a>
</div>
</div>
</li>
</ul>
And this is what one of the cards looks like: Project Card Screenshot
There are two ways to handle cards. One is to make the whole thing clickable and one is to have individual items within the card clickable. At the moment it appears you are trying to achieve both which is not possible. (ok it is possible, it is just a terrible idea and will cause all sorts of headaches for people iof you try and nest hyperlinks).
Given that you have two links within the cards going to different places we should go with option 2.
I will focus on a couple of improvements you could make based on the HTML provided based on having two links in the card.
Your HTML is pretty good already, just a couple of minor points.
You have added tabindex="0"
to make the whole card able to receive focus. This has no benefit (due to the fact that you have multiple links in the card as mentioned previously) and is unnecessary.
The golden rule for tab stops is only make something focusable if it can perform an action. Keyboard users without sight impairments will thank you for not adding extra tab stops and screen reader users navigate via headings, links sections etc. so they have no need for you to make things focusable that don't have actions.
For sighted users there is no issue with "view Demo" and "View Code" as they can see the relationship visually on the page.
But screen reader users may navigate by links to get a feel for the page / find what they are looking for.
For screen reader users "View Demo" is useless as a description.
You have two options.
I would go with the first option if you can change the design to accommodate the extra text.
Also because we now want each link to be focusable you need to remove the tabindex="-1"
.
One final point, if you are making links open in a new window it is a good practice to indicate that fact.
One thing that I believe is acceptable (as writing "(opens in new window)" after each link is just not practical) is to have a tiny icon that indicates it opens in a new window.
By using a little CSS trickery we can make the process automatic.
a[target="_blank"]::after {
content: '\29C9';
content: '\29C9' / " (opens in new window)";
margin: 0 3px 0 5px;
}
Notice how I define the content
twice? The first one is recognised by all browsers, the second one uses content: alternative text
so that it adds "(opens in new window)" for screen readers.
Also the character I chose is not agreed upon as a standard but it works for most purposes.
This is just something to draw attention to. If the image does not add any value to the information on the page it should be decorative. By value I mean that the information within the image does not add any extra information.
It is impossible to advise based on the example given but if the image is purely a screenshot of the product then either improve the description to explain what the image shows in context (so what process it is depicting) or just make it decorative.
You can make an image decorative by simply leaving the alt
attribute as an empty string. But you must still have the attribute. So <img alt=""/>
is ok, but <img alt />
would not be. Using alt=""
will make sure a screen reader ignores the image.
I have added comments above the parts I changed.
The key part is the CSS to visually hide an item (but leave it accessible for screen readers).
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
/****adds a nice little icon to show a new window ****/
a[target="_blank"]::after {
content: '\29C9';
content: '\29C9' / " (opens in new window)";
margin: 0 3px 0 5px;
}
<ul>
<!-- removed the tabindex -->
<li>
<h3>Project Name</h3>
<img src="https://via.placeholder.com/744.png" alt="Preview Image of X project">
<div>
<p>
Project Description
</p>
<div>
<!-- added a visually-hidden span to make the link text make sense on its own, also removed the `tabindex="-1"` to make the links focusable-->
<a href="{Link to live page}" target="_blank">View Demo <span class="visually-hidden">for project X</span></a>
<a href="{Link to Github Repo}" target="_blank">View Code <span class="visually-hidden">for project X</span></a>
</div>
</div>
</li>
<li>
<h3>Project Name</h3>
<img src="https://via.placeholder.com/744.png" alt="Preview Image of Y project">
<div>
<p>
Project Description
</p>
<div>
<a href="{Link to live page}" target="_blank">View Demo <span class="visually-hidden">for project Y</span></a>
<a href="{Link to Github Repo}" target="_blank">View Code <span class="visually-hidden">for project Y</span></a>
</div>
</div>
</li>
</ul>