Web Accessibility: Working with Images and Content
When we create a website, the content is more than just text. As I learned in my previous article, accessibility is about more than just aria-label
or alt
attributes in images. Sometimes we add more than images, like SVGs, charts, or even consider contrast or a glowing background.
When we think about accessibility, we might first think of blindness, but what happens when someone has an accident and can't use a computer, or they are in areas with too much light, or have issues with vision after surgery and find it difficult to read text (I know this from experience)?
Today, I want to share with you things I've learned about Accessibility in the last few days! Let's do it!
If you want to test all these cases, I highly recommend using a screen reader like VoiceOver for Mac users or NVDA for Windows.
Types of Images
When we add images to our websites, some of them serve a functional purpose while others are decorative. What's the difference?
Decorative: These work as styling elements or to make the UI attractive without conveying a text or message, like a fancy background. These images aren't necessary for functionality or conveying information.
Functional: These are included in the app because they are useful for an action, like social network icons, or images that contain information like text or charts for stats, or an image with text to take an action, like a banner with a promotion to get a discount or signup.
Handling Decorative Images
For accessibility, decorative images are not important or relevant. If you use a screen reader, describing an image that's only for the background is not important. It's important to notify that an image is decorative by using alt=""
without a title or role, so the screen reader can skip it.
For example:
<main>
<img src="fancy-background.jpg" alt=""/>
</main>
But if you leave the image without an alt attribute like <img src="fancy-background.jpg"/>
, the screen reader will notify the user about it.
Handling Functional Images
What is a functional image? these are images that serve a purpose in the application. like an image with a promotion with a referral link and discount, or social media icons or graph charts.
The information is provided by using the alt
attribute. For example, in the following markup, the screen reader skips the fancy border image and announces "LeBron James NBA Player".
<main>
<img src="fancy-border.jpg" alt=""/>
<img src="lebron-james.jpg" alt="LeBron James NBA Player"/>
</main>
Sometimes we have images outside the viewport that appear due to some JavaScript code. Regardless of whether the image is outside the viewport, the screen reader still works with the HTML markup.
To ensure the screen reader ignores these images, we can use the CSS display: none
or the attributes hidden
or aria-hidden
.
In the following examples, the screen reader will disregard the image::
<main>
<h1>The NBA</h1>
<img src="lebron-james.jpg" alt="LeBron James NBA Player" aria-hidden />
<img src="lebron-james.jpg" alt="LeBron James NBA Player" hidden />
</main>
Did you know that alt text can help with SEO? ๐
How to Make Accessible Images in CSS?
Most background images and icons use images or icon fonts in CSS. I recommend using CSS images only for decorative purposes, not for functional ones; however, this doesn't always happen in the real world.
For example, here is a background image defined in CSS:
.logo {
background-image: url('../logo.png');
background-repeat: no-repeat, repeat;
height: 24em;
width: 100%;
}
Now, I can apply it to various elements and customize it based on the specific element. For example:
The aria-label
works similar to alt
, it doesn't appear for sighted visitors, but the screen reader conveys this information, along with any additional content inside.
<span class="logo" aria-label="Welcome to NBA">
Purchase game now!
</span>
<div class="logo" aria-label="Welcome to NBA">
Purchase game now!
</div>
This approach works, but it seems like we are giving too much responsibility to the span
and the div
to display the background and contain text. Also, this approach doesn't work well with other elements that have a specific role, like buttons.
A more effective solution is to restructure our HTML using an element dedicated to a single purpose.
Example:
<div>
Purchase game now!
<span class="logo" aria-label="Welcome to NBA"></span>
</div>
<button>
Purchase <span class="logo" aria-label="Welcome to NBA"></span>
</button>
How to Provide All Information?
In the previous examples, it's straightforward because it involves a single image or button. However, what about the NBA stats containing all the information about game statistics? Do I need to provide lengthy text?
For example, in the following image
<img src="./gianis.png" alt="Giannis Antetokounmpo Game Stats">
We add the image and use the alt
attribute to provide a description, but some information about the stats is naturally missing. One possible solution is to add an p
element containing the extra information.
<img src="./gianis.png" alt="Giannis Antetokounmpo Breaks Record">
<p>Giannis Antetokounmpo becomes the first player to have 45 points, 10 rebounds, 5 assists, and 0 turnovers in a game since Michael Jordan in 1989!</p>
This works, but sighted users will see the duplicate information. What can we do to address this?
In this situation, a suitable approach is to hide the text from the viewport. For instance, if you use Kendo UI, it offers the class .k-sr-only
to hide the elements from the viewport while keeping them accessible to screen readers. Alternatively, you can create your own solution.
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
Another alternative method is to use aria-describedby
by linking the image to a paragraph and removing it from the current markup structure.
<img src="./gianis.png" alt="Giannis Antetokounmpo Breaks Record"
aria-describedby="gianis-stats">
<p class="sr-only" id="gianis-stats">
Giannis Antetokounmpo becomes the first player to
have 45 points, 10 rebounds, 5 assists, and 0 turnovers
in a game since Michael Jordan in 1989!
</p>
Perfect! Now we have a great definition of the stats in an accessible mode!
Content Contrast
The content is the next part of our websites when we struggle to read the text because it sometimes has a background color and text with low contrast.
Sometimes, you are on a screen with low brightness or a place with too much light, so we must provide contrast to make readable the content, but not all content is the same we have large and standard text.
Chrome can help you understand these visual impairments by letting you simulate color vision deficiencies.
How do we work the contrast?
The standard text must have 4.5:1 contrast, for equals or higher than 18 points, bold equals or higher than 14 then 3.1, which makes it easy to read.
Also, the form inputs, buttons, or icons must have 3.1 contrast, the only exception is disabled.
You have the following tools to check the controls or links contrast:
Chrome extension WCAG color contrast checker.
Links contrast checker: https://webaim.org/resources/linkcontrastchecker/
Normal, Large text and components: https://webaim.org/resources/contrastchecker/
Recap
We learned the difference between decorative and functional images, how to handle them, and how screen readers can skip decorative images using CSS properties or HTML attributes like hidden and aria-hidden.
We also explored techniques for providing large amounts of information without breaking our design combining it with aria-describedby
and how to provide a good contrast for color vision deficiencies.
I hope this information is useful if you are starting in the accessibility world like me.
Subscribe to my newsletter
Read articles from Dany Paredes directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Dany Paredes
Dany Paredes
I'm passionate about front-end development, specializing in building UI libraries and working with technologies like Angular, NgRx, Accessibility, and micro-frontends. In my free time, I enjoy writing content for the Google Dev Library, This Is Angular Community, Kendo UI, and sharing insights here.