Throughout the previous modules we kept deferring the detail of text alternatives "until Module 5". The moment to settle that debt has arrived. Criterion 1.1.1 (Non-text Content) is level A and is, probably, the most violated on the entire web: it requires that every image have an appropriate text alternative... and "appropriate" does not always mean "describe what you see". The same image file may need a long alt, an empty alt, or a description of an action, depending on its function on the page. In this lesson we build a decision tree that we will apply to the real images of Cursalia: the course thumbnail, the logo, the category icons, and the student's progress chart. With it, we close Module 5.

Contents

  1. Why the correct alt depends on the function, not the image
  2. The alt decision tree
  3. Decorative, informative, functional, text, and complex images
  4. How to write a good alt
  5. figure and figcaption
  6. SVG, icons, and CSS background images
  7. Applying it to Cursalia
  8. Common mistakes, exercises, and conclusion

  1. Why the correct alt depends on the function

Marta, using NVDA, does not see the image: she hears what you put in the alt. And here is the idea that changes everything: the same photo may require completely different alternatives depending on what it is there for. A photo of a padlock can be:

  • pure decoration next to a headline → alt="" (so the AT ignores it),
  • the illustration of an article about security → alt="Closed padlock on a keyboard" (it informs),
  • the icon of a "lock account" button → alt="Lock account" (it describes the action).

That is why there is no "correct" alt in the abstract: first you decide what function the image serves and the alternative follows from that.

  1. The alt decision tree

flowchart TD
  A[Does the image convey information<br/>or serve a function?] -->|No, it's decorative| B["empty alt"]
  A -->|Yes| C{Is it interactive?<br/>link or button}
  C -->|Yes, functional| D[alt describes the ACTION<br/>not the image]
  C -->|No| E{What kind of<br/>information?}
  E -->|Simple content| F[alt describes the information]
  E -->|It's text inside<br/>the image| G[Avoid it; if not,<br/>alt with the exact text]
  E -->|Complex chart/diagram| H[short alt +<br/>adjacent long description]

Walk this tree for each image. The first question —"does it convey anything or is it just ornament?"— is the most important and the one most people skip.

  1. The five types of image

Decorative

It conveys no information: separators, ornamental backgrounds, a generic filler photo next to text that already says it all. It must be ignored by assistive technology, and for that the alt must be empty but present:

<!-- GOOD: empty alt → NVDA skips it entirely -->
<img src="ornament.svg" alt="">

<!-- BAD: no alt → some readers read the file name: "ornament dot svg" -->
<img src="ornament.svg">

<!-- BAD: redundant alt that only generates noise -->
<img src="ornament.svg" alt="decorative ornamental image">

The difference between alt="" and omitting alt is enormous: alt="" explicitly says "there is nothing to announce"; omitting the attribute makes many readers read out the file URL. An equivalent alternative: role="presentation" (or role="none"), though alt="" is the simplest and most robust.

Informative

It conveys information that the surrounding text does not provide. The alt must communicate that information, concisely:

<!-- The image provides a fact; the alt conveys it -->
<img src="growth-chart.png"
     alt="Enrollments grew 40% between January and June">

Ask yourself: "if I removed the image and replaced it with this text, would the reader get the same thing?". If the answer is yes, your alt is good.

Functional

The image is inside a link or a button and represents its action. Here the alt does not describe the image, it describes what it does:

<!-- BAD: describes the image; Marta hears "Cursalia logo" and doesn't know it's a useful link -->
<a href="/"><img src="logo.svg" alt="Cursalia logo"></a>

<!-- GOOD: describes the link's ACTION -->
<a href="/"><img src="logo.svg" alt="Cursalia, go to home"></a>

<!-- Icon inside a button: the alt/label is the action -->
<button><img src="magnifier.svg" alt="Search"></button>

If a <button> contains only an SVG icon, hide the SVG with aria-hidden="true" and put the name on the button itself with aria-label (as we saw in the player in 05-03).

Text

An image whose content is text (a "Buy" button rendered as an image, a headline in a JPG). It should be avoided: it does not scale, cannot be selected, gets worse with Sofía's zoom, and violates criterion 1.4.5 (Images of Text). Use real text with CSS. If it is unavoidable (a logo with a tagline), the alt must contain the exact text:

<!-- Avoid it. But if there is no other option: -->
<img src="offer.png" alt="Sale: 50% off until June 30">

Complex

Charts, diagrams, maps, infographics: they contain too much information for a short alt. The technique is twofold: a short alt that gives the headline, and an adjacent long description (or one linked with aria-describedby):

<img src="student-progress.png"
     alt="Student progress by module"
     aria-describedby="progress-desc">

<div id="progress-desc">
  Module 1: 100% complete. Module 2: 80%. Module 3: 45%.
  Modules 4 to 7: not started. Total course progress: 46%.
</div>

The short alt ("Student progress by module") lets Marta decide whether she wants the detail; the long description, referenced with aria-describedby, gives her the full data. That description also benefits everyone: it is real, indexable, and selectable text.

  1. How to write a good alt

Practical rules:

  • Concise. One sentence usually suffices. Readers do not let you pause partway through an endless alt.
  • No "image of" / "photo of". The AT already announces that it is an image; adding "image of..." is redundant and annoying. Write the content directly.
  • Contextual. The same picture takes a different alt in an article than in a button. Think about the function.
  • No keyword stuffing. The alt is not for forced SEO; filling it with keywords harms Marta and gets penalized just the same.
  • Punctuate. A final period makes the reader pause naturally.
Instead of… Write…
alt="image" alt="" (if decorative) or the real content
alt="photo of a person coding on a laptop" alt="Developer writing code" (if it conveys) or alt="" (if it's filler)
alt="logo" on a home link alt="Cursalia, go to home"
alt="chart.png" alt="Total course progress: 46%"

  1. figure and figcaption

When an image has a caption visible to everyone, use <figure> with <figcaption>. Careful: the figcaption does not replace the alt; they serve different purposes. The alt describes the image for those who cannot see it; the figcaption is a caption for everyone.

<figure>
  <img src="accessibility-tree.png"
       alt="Accessibility tree derived from the DOM, with roles and names">
  <figcaption>Figure 3. The browser builds the accessibility tree from the DOM.</figcaption>
</figure>

Sometimes the figcaption already describes everything and the alt can be short or empty to avoid duplication; but by default fill both with complementary content.

  1. SVG, icons, and CSS background images

Inline SVG. An <svg> has no alt attribute. To make it accessible as an image, give it role="img" and a name with <title> or aria-label; if it is decorative, aria-hidden="true":

<!-- Informative SVG -->
<svg role="img" aria-labelledby="t1"><title id="t1">Course completed</title>…</svg>

<!-- Decorative SVG inside a button that already has text -->
<button>Save <svg aria-hidden="true" focusable="false">…</svg></button>

The focusable="false" prevents some browsers (old Edge/IE) from focusing the SVG and creating phantom tab stops.

Icons. Two techniques:

  • Icon fonts (an <i> with an icon-font character): always aria-hidden="true", because the character can be read as a strange symbol. The meaning goes in separate text.
  • SVG is preferable: it scales crisply and is easier to control. Same principle: if the icon accompanies text, aria-hidden; if the icon is the only information (an icon-only button), give it a name with aria-label on the control.
<!-- Decorative icon next to text: hidden from the AT -->
<a href="/certificates"><i class="bi bi-award" aria-hidden="true"></i> Certificates</a>

<!-- Icon-only button: the name goes on the control, the icon is hidden -->
<button aria-label="Close"><i class="bi bi-x" aria-hidden="true"></i></button>

CSS background images (background-image). They are not accessible: they are not in the accessibility tree and do not accept alt. That is why they are fine for pure decoration, but they must never carry information. If a background-image conveys something (a status icon, a chart), it is a mistake: move it to an <img> with alt or add a visible/hidden text alternative.

  1. Applying it to Cursalia

Let's walk through the platform's real images with the decision tree:

Cursalia image Type Correct alternative
Course thumbnail on the catalog card Functional (the whole card is a link) or informative If the course title is already present as text on the card, the thumbnail is decorativealt="" (prevents Marta from hearing the title twice). If the thumbnail were the only link, alt="View course: Web Accessibility".
Logo in the header, inside the home link Functional alt="Cursalia, go to home" (describes the action, not "logo").
Category icons (bootstrap-icons) next to the name Decorative (there is text alongside) aria-hidden="true" on the icon; the category name is given by the text.
Progress chart on the student dashboard Complex Short alt ("Progress by module") + long description with the percentages via aria-describedby.

The thumbnail case is the most instructive: on a catalog card, the course title is almost always already present as text, so giving it an alt with the same title makes Marta hear it twice. The thumbnail becomes decorative (alt="") precisely because its information is already covered by the text. Once again: function rules over visual content.

Common Mistakes and Tips

  • Omitting the alt instead of alt="". Without an alt, many readers read out the file URL. For decorative images, use an explicit alt="".
  • Writing "image of..." / "photo of...". Redundant: the AT already announces that it is an image.
  • Describing the image on a functional element. On a logo-link, alt="logo" does not say where it leads. Describe the action.
  • Cramming a complex chart into a 300-character alt. No one can hear that in one go. Use a short alt + a long description.
  • Information in a background-image. It does not reach the AT. CSS backgrounds are for decoration only.
  • Duplicating the course title on the thumbnail. Marta hears it twice. If the text is already there, alt="".
  • Tip: for any image, ask yourself two questions in order: (1) does it convey information or a function, or is it decoration? and (2) is it interactive?. With those two answers, the decision tree gives you the correct alt.

Exercises

Exercise 1. For each Cursalia image, indicate the type and the appropriate alt (or technique): (a) an ornamental divider line between sections; (b) the logo inside the home link; (c) the bar chart of the student's progress.

Exercise 2. This code for a catalog card has an accessibility problem. Spot it and fix it.

<a href="/course/accessibility">
  <img src="thumb.jpg" alt="Web Accessibility">
  <h3>Web Accessibility</h3>
</a>

Exercise 3. You have a button that contains only an SVG of a trash can, used to delete an item. Write the accessible HTML.

Solutions

Solution 1. (a) Decorative<img src="line.svg" alt=""> (or a CSS background, since it is pure decoration). (b) Functional<a href="/"><img src="logo.svg" alt="Cursalia, go to home"></a>; the alt describes the action, not "logo". (c) Complex → short alt="Progress by module" + an adjacent long description with each module's percentages, linked with aria-describedby.

Solution 2. The problem is duplication: the thumbnail's alt repeats the title that is already in the <h3>. Marta would hear "Web Accessibility" twice. Since the information is already in text, the thumbnail is decorative:

<a href="/course/accessibility">
  <img src="thumb.jpg" alt="">
  <h3>Web Accessibility</h3>
</a>

Solution 3. The icon-only button needs a name on the control and the SVG hidden from the AT:

<button type="button" aria-label="Delete">
  <svg aria-hidden="true" focusable="false"><!-- trash can icon --></svg>
</button>

The aria-label="Delete" provides the accessible name (it describes the action); aria-hidden="true" prevents the SVG from being announced; focusable="false" avoids phantom tab stops.

Conclusion

With this lesson we close Module 5. You no longer look at an image and wonder "what do I put in the alt?": you walk the decision tree —decorative, informative, functional, text, or complex— and the image's function dictates the answer. And with that we also close the build phase of the course: in modules 1 to 5 we have learned what accessibility is, why it matters, what WCAG requires, and how to implement it —semantic structure, forms, ARIA, contrast, JavaScript widgets, keyboard, multimedia, and images—. We know how to build accessibly.

Now the decisive question remains: does what we have built actually work? An aria-expanded may be out of sync, a focus trap may have a leak, an alt may sound terrible with NVDA. All of that has to be verified. In Module 6 we will learn to check accessibility systematically: manual testing (keyboard and screen reader), automated tools (axe, Lighthouse) and their limits, testing with real users and assistive technologies, and interpreting audit reports. We move from building to proving that Cursalia is truly accessible.

© Copyright 2026. All rights reserved