kram08980
kram08980

Reputation: 99

Correct a11y declaration for a link with just a background image

I'm trying to find the best way to improve a11y for links that are built just using background images inside a span (the old school massive icons spritesheets approach). They're part of a large website and changing the whole icon system isn't a realistic scenario right now.

What we basically have are these two different links all around;

First one being the problem:

<a href="#" aria-label="Functionality Description">
  <span class="icon-functionality"></span>
</a>

The other link style has text in it, so should be fine.

<a href="#" aria-label="Functionality Description">
   <span class="icon-text">Functionality</span>
   <span class="icon-functionality"></span>
</a>

Trying to find out what should we do in the first case, I found a solution that I'm not sure about; giving the span containing the background the role="img" and an empty alt attribute.

This way, the anchor has an image in it, and by using the empty alt attribute, the screen reader would understand it's a decorative picture. In this case, the reader has the aria-label associated to the anchor to 'understand' the funcitonality.

<a href="#" aria-label="Functionality Description">
  <span class="icon-functionality" role="img" alt></span>
</a>

Although I know it's not ideal and in a long term basis we may want to change the whole icon system, would this be enough to provide a decent a11y? What do you think?

All recommendations are welcome. Massive thanks in advance!

Edit to add a screenshot of the Siteimprove error given:

Siteimprove error given

Upvotes: 2

Views: 394

Answers (1)

GrahamTheDev
GrahamTheDev

Reputation: 24825

Short Answer

There is nothing wrong with the current implementation across the site using aria-labels. Your improved example is actually worse for accessibility if the aria-label is not read.

Longer Answer

A background image will not be announced by screen readers and is assumed to be purely decorative.

So the following (your first example) is perfectly acceptable:

<a href="#" aria-label="Functionality Description">
  <span class="icon-functionality"></span>
</a>

The aria-label will provide all of the information a screen reader needs.

In your second example the aria-label will override the contents anyway so the icon-text is irrelevant as far as a screen reader is concerned.

In your third example you have the same thing with the aria-label overriding the contents.

With that being said if you didn't have an aria-label having a null alt attribute is not correct, it should be an empty alt attribute to be hidden. (So alt="" not alt, otherwise the screen reader will attempt to find a name for the image (which could result in unexpected behaviour with a background image).

You also now introduced the background image into the accessibility tree (as it would have been ignored before) with role="img" so actually made more work for yourself.

The best Option

A better option is visually hidden text if you are able to implement that, as it has better compatibility (aria-label isn't 100% supported in all scenarios surprisingly) and visually hidden text works in text only browsers.

If you are able to do this then this is the better way to do things due to compatibility, but your aria-label method is fine in 99% of scenarios so don't worry too much if this is difficult to implement.

In the following example I have included an inline SVG for demonstration purposes instead of your background image, but the key part is the additional <span> with the visually-hidden class.

a{
    width: 25%;
    display: block;
}

.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 */
}
<a href="#">
  <span class="icon-functionality">
  <!----ignore this SVG it is for demonstration purposes only-->
  <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
        <path fill="#666" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z">
        </path>
    </svg></span>
  <!----This is the key part, use this instead of `aria-label` if you can.-->
  <span class="visually-hidden">Functionality Description</span>
</a>

Additional thoughts

Just a quick one but I hope the href="#" is for demonstration purposes only.

If you find any anchors on the site using href="#" this is an anti-pattern and a bad practice for accessibility.

Instead these should be buttons if they perform an action otherwise they should be valid URLs if they are for navigation.

I only raise this concern as your aria-label says "Functionality Description", which makes me think you are using anchors for buttons.

I can link you to several answers on this if you need more info on why this is important for accessibility.

Upvotes: 2

Related Questions