Topic 7.2
Writing Good Alt Text
In one line
Alt text is the words that replace an image for people who can't see it: describe what the image means in this place, use alt="" for decoration, and never leave alt out.
Think of it like this
Describing photos to a friend on the phone. You wouldn't say "there's a JPG file here". You'd say what matters: "it's the red bike I told you about". And you'd skip the boring parts: you wouldn't describe the wallpaper. Alt text is that phone call, written down once for everyone who can't see the picture.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Alt text
- The words in an image's
altattribute, read in place of the image when it can't be seen. - Informative image
- An image that adds information the text around it doesn't already give.
- Decorative image
- An image that's only for looks. It gets
alt=""so screen readers skip it. - Functional image
- An image that is the only content of a link or button. Its alt describes what clicking does.
- Complex image
- A chart, map or diagram with too much information for one sentence. It needs a longer description nearby.
- Empty alt
alt="": a deliberate signal that the image is decoration.- aria-hidden
- An attribute,
aria-hidden="true", that removes an element from the accessibility tree so assistive tech ignores it.
Step by step
01Ask the decision question
For each image, ask: if I removed it, would a reader lose information or the ability to do something? Then follow the tree below. W3C's "alt decision tree" tutorial asks the same questions in more detail.
02Informative: say what matters
Describe the content that matters in this context, in plain words, ending with a full stop so screen readers pause.
<img src="asha.jpg" alt="Asha presenting the new checkout design to the team." width="600" height="400">03Decorative and functional
The swirl adds nothing, so its alt is empty. The logo is the only thing in the link, so its alt is the destination. The icon next to the word "Print" would be read twice, so it's hidden from assistive tech.
<img src="swirl.svg" alt="">
<a href="/"><img src="logo.svg" alt="Hectal home"></a>
<button type="button">
<svg aria-hidden="true" focusable="false" width="16" height="16"><!-- printer --></svg>
Print
</button>04Complex: short alt plus a full description
The alt gives the headline. The caption, or a details element, gives every number in text, so screen reader users, people with low vision and search engines all get the data.
<figure>
<img src="sales.png" alt="Bar chart: sales doubled from 2023 to 2024.">
<figcaption>
Sales by year.
<details>
<summary>Chart data</summary>
<p>2022: 40 orders. 2023: 60 orders. 2024: 120 orders.</p>
</details>
</figcaption>
</figure>05Icon-only buttons
When a button contains only an icon, the button needs the name. Hide the SVG itself and label the button with aria-label. (Topic 7.4 explains aria-label; Topic 7.5 explains how the name is computed.)
<button type="button" aria-label="Close">
<svg aria-hidden="true" focusable="false" viewBox="0 0 16 16" width="16" height="16">
<path d="M3 3l10 10M13 3L3 13" stroke="currentColor" stroke-width="2"/>
</svg>
</button>Try it yourself
- 1
Fix the missing alt
In the first example, image c is a plain green square used as a divider. Predict what the log will say after you add
alt=""to it, then run it. - 2
Break a name
In the second example, delete
aria-label="Close". Predict the name the log prints forclose, then run it. That empty name is what a screen reader user would get: "button". - 3
Write alt for context
Change the alt of image a so it works on a page about traffic lights instead of a server status page. Notice how the same picture needs different words.
Code & diagrams
Images b and c both report `img.alt` as an empty string. Only `hasAttribute("alt")` tells decorative and missing apart.
Preview
Console
Nothing logged yet.Expected console output
a | img.alt = "Red warning light: the server is down." | informative: Red warning light: the server is down.
b | img.alt = "" | decorative (skipped)
c | img.alt = "" | MISSING alt (a screen reader may read the file name)Each control gets its name from a different place: the image's alt, aria-label, or its own text. The SVGs are hidden so they add nothing.
Preview
Console
Nothing logged yet.Expected console output
logo -> Hectal home
close -> Close
print -> PrintBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Leave alt off a logo link
Write <a href="/"><img src="logo.svg"></a> with no alt and no text in the link.
Break #2
Describe the picture instead of the purpose
Give a search button's icon alt="magnifying glass".
Myth vs fact
Myth
alt="" and no alt attribute are the same.
Fact
Empty alt marks the image as decoration and screen readers skip it. Missing alt means "unknown", so screen readers may read the file name, and the validator reports an error.
Myth
Start alt text with "Image of…" so people know it's an image.
Fact
Screen readers already announce "image" or "graphic". Start with what matters.
Myth
Every image needs a long, detailed description.
Fact
Describe only what matters in context. A decorative image needs nothing, and most informative images need one short sentence.
Myth
The title attribute is a good alternative to alt.
Fact
title shows only as a mouse-hover tooltip, isn't shown on touch screens or to keyboard users, and is announced inconsistently. Use alt.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
When an image fails to load, Chromium renders the alt text inside the image's box (if it fits); if
altis empty, it shows nothing. This is another reason for meaningful alt: it's also the fallback for slow or broken networks. - ▸
Per the HTML spec, an
<img>withalt=""maps to the presentation role (in ARIA 1.2 also callednone) and drops out of the accessibility tree. Addingrole="presentation"to an image that has non-empty alt is an author error. - ▸
Inline
<svg>in older versions of Internet Explorer and old Edge was focusable by default, hence thefocusable="false"habit on icon SVGs. Modern browsers don't need it, but it's harmless and still common in design systems. - ▸
AI-generated alt text (in some CMSs and browsers) can describe what's visible but not why it's on the page. Treat it as a draft for a human to edit, never as the final answer.
Remember this
- 1
The
altattribute (short for alternative text) is read aloud by screen readers in place of the image, shown by browsers when the image fails to load, and used by search engines to understand the image. WCAG 1.1.1 Non-text Content (level A) requires a text alternative for every image that carries meaning. - 2
There are three kinds of
alt. Informative images add information: write a short description of what they show that matters here (alt="Asha holding the 2024 coding trophy"). Decorative images add nothing (a swirl, a background flourish, a photo that repeats the text beside it): write an empty alt,alt="", so screen readers skip them. Functional images are the only content of a link or button: describe the action or destination, not the picture (alt="Home"for a logo linking to the home page,alt="Search"for a magnifier icon button). - 3
Missing alt is not the same as empty alt. With
alt=""you are saying "this is decoration, skip it". With noaltat all, the browser doesn't know, so many screen readers announce the file name instead: "IMG underscore 4032 dot jpeg". The validator reports a missingaltas an error. In JavaScript,img.altreturns""in both cases, so check withimg.hasAttribute("alt"). - 4
Good alt text is short and specific (usually one sentence, often under about 125 characters, though that's a habit, not a rule), doesn't start with "image of" or "picture of" (the screen reader already says "image" or "graphic"), includes any text shown in the image (a banner saying "50% off" needs those words), and depends on context: the same photo of a dog might be
alt="Bruno, our office dog"on a team page andalt="Golden retriever with a short, glossy coat"on a dog-breed guide. - 5
Complex images like charts, graphs, maps and diagrams can't be summed up in one sentence. Give a short
altthat says what it is and the main point (alt="Bar chart: sales doubled from 2023 to 2024"), then put the full details as real text nearby: a<figcaption>(Topic 2.5), a data table, or a<details>element with the numbers. Everyone benefits from the data being in text. - 6
Icons and SVG. An
<svg>written inline has noaltattribute. If the icon is decorative or sits next to visible text, hide it witharia-hidden="true"so it isn't read twice. If the icon is the only content of a button or link, give the button a name (aria-label="Close"or visually hidden text). An SVG that stands alone as meaningful content can userole="img"witharia-label, or a<title>as its first child. CSSbackground-images are invisible to assistive tech, so never put meaningful images there.
Explain it without notes
What's the difference between alt="" and a missing alt attribute, for screen readers and for validation?
How do you write alt text for an image that is the only content of a link?
How do you make a chart accessible?
How do you make an icon-only button accessible when the icon is an inline SVG?
Practice
Write HTML for a product page header: a decorative divider image, a logo that links to /, and a cart link that contains only an icon image.
A page shows a photo of a cake with the visible caption "Mum's chocolate cake" directly underneath. What alt should the photo have, and why?
Trade-offs
- ↔
Detailed alt helps understanding but is slow to listen to; keep alt short and put long descriptions in visible text that everyone can use.
- ↔
Marking an image decorative removes it for screen reader users; if in doubt about whether it adds meaning, ask what a reader would lose, and describe it if the answer is "something".
Done when you can
I can tell informative, decorative, functional and complex images apart.
I give decorative images
alt=""and never leave alt out.I write functional alt as the action or destination.
I give charts a short alt plus a full text description.
I hide icon SVGs with
aria-hiddenand name the button instead.