SVG title, desc and alt text: accessible SVG
How to give an SVG a text alternative: alt on an img tag, title and desc with role img for inline SVG, and aria-hidden for decoration. Code for each case.
Published
An SVG gets its text alternative in one of two ways, depending on how it is placed. An SVG file shown with <img> takes an alt attribute, like any other picture. An SVG written inline in the page has no alt: it is named by a <title> element inside it, or by aria-label, and should be marked role="img" so that it is announced as one image. A longer explanation goes in <desc>. An SVG that is only decoration should be hidden from screen readers.
Which method for which case
| How the SVG is used | Give it a text alternative with |
|---|---|
<img src="chart.svg"> | alt="..." on the <img> |
Inline <svg> that carries meaning | role="img" with a <title>, or with aria-label |
Inline <svg> beside text that already says the same thing | aria-hidden="true", and no title |
| Inline icon alone inside a button or link | A name on the button or link. Hide the SVG |
| CSS background | Nothing can be attached. Use it for decoration only |
SVG in HTML compares these ways of placing an SVG.
An SVG in an img tag
<img src="sales-chart.svg" alt="Bar chart: sales rose each month from January to June" width="400" height="300">
The alt text is what a screen reader speaks and what appears if the file fails to load. For a decorative image, write alt="", which tells assistive technology to pass over it.
A <title> inside the file does not do this job. When an SVG is loaded through <img>, the browser treats the file as a sealed picture and takes the name from the alt attribute only. In a test in Chrome, an <img> with no alt pointing at an SVG that had a <title> was given no accessible name at all.
Inline SVG: title and desc
<title> and <desc> are elements, written as children of the thing they describe. This example is for pasting into an HTML page:
<svg role="img" aria-labelledby="chart-title" viewBox="0 0 120 60" width="240" height="120">
<title id="chart-title">Sales by month</title>
<desc>Three bars rising from January to March.</desc>
<rect x="10" y="40" width="20" height="20" fill="teal"/>
<rect x="50" y="25" width="20" height="35" fill="teal"/>
<rect x="90" y="10" width="20" height="50" fill="teal"/>
</svg>
<title>is the short name, the equivalent of alt text. Make it the first child of the<svg>.<desc>is a longer description for anyone who wants more. It is never shown on screen.role="img"tells assistive technology to treat the whole drawing as one image and not to read through the shapes inside.aria-labelledbypoints at the title’s id. Current browsers find the title without it, but pairs of older browsers and screen readers have been inconsistent, and the explicit link costs nothing. Ids must be unique on the page.
A shorter form with the same result for a screen reader, and no tooltip:
<svg role="img" aria-label="Sales by month" viewBox="0 0 120 60" width="240" height="120">
<rect x="10" y="40" width="20" height="20" fill="teal"/>
</svg>
Is the SVG title read by screen readers?
Usually, for inline SVG, but not dependably when left to chance. Tested in Chrome, an inline <svg> with a <title> is exposed as an image named by the title, and one without a title is still exposed, as an image with no name. Other browsers and screen readers have differed over the years. Adding role="img" and aria-labelledby, or using aria-label, removes the doubt.
There is no title attribute in SVG
HTML elements take a title attribute. SVG elements do not: <svg title="Logo"> and <path title="..."> show no tooltip and are not a dependable name. The attribute is not part of SVG, though Chrome used it as a fallback name in a test. In SVG the title is always a child element:
<svg viewBox="0 0 100 50" width="200" height="100">
<rect width="40" height="40" fill="gold">
<title>Gold: 40 units</title>
</rect>
<rect x="50" width="40" height="40" fill="teal">
<title>Teal: 40 units</title>
</rect>
</svg>
Each rectangle has its own title, and browsers show it as a tooltip when the pointer rests on that shape. This is how the parts of a chart or a map are labelled.
The tooltip is drawn by the browser and cannot be styled with CSS. It does not appear on touch screens, so never put information there that is not available some other way. To name an SVG without a tooltip, use aria-label instead of <title>.
Decorative SVG
An icon next to a word that says the same thing adds nothing for a screen reader user. Hide it:
<a href="/downloads/">
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16">
<path d="M8 1v9M4 7l4 4 4-4M2 14h12" fill="none" stroke="currentColor" stroke-width="2"/>
</svg>
Downloads
</a>
aria-hidden="true" removes the SVG and everything in it from what is read out. The link is announced as “Downloads”.
An icon with no text beside it
When the icon is the whole content of a button or link, name the control and hide the drawing:
<button type="button" aria-label="Close">
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16">
<path d="M3 3l10 10M13 3L3 13" stroke="currentColor" stroke-width="2"/>
</svg>
</button>
The button is announced as “Close, button”. Putting a <title> in the SVG and leaving the control bare also gave it a name when tested in Chrome, but naming the control directly is the more dependable pattern.
Text inside an SVG
Words written with <text> are real text. They can be read aloud, selected and found by a search of the page, provided the SVG is inline and not hidden. Words that have been converted to paths, as they are in most logos and in files for cutting machines, are only shapes: the title or the alt text has to carry them. SVG text covers the element.
In a standalone file
In an .svg file opened on its own, a <title> that is a child of the root element is the document’s title, shown in the browser tab. Some drawing programs write one from the file or layer name, so it is worth checking that it says something sensible. The SVG viewer shows the code of any file, and the SVG optimizer leaves <title> and <desc> in place when it strips the rest.
Writing a good text alternative
- Say what the picture tells the reader, not what it looks like: “Sales rose each month” before “bar chart with six bars”.
- Keep the title short. Put detail in
<desc>or, better, in the text of the page where everyone can read it. - For a logo, the name of the organisation is enough.
- Do not begin with “Image of”. Screen readers already announce that it is an image.
- Colour alone should not carry meaning. Label the parts.
Common problems
| What you see or hear | Cause | Fix |
|---|---|---|
| A screen reader reads nothing for an SVG image | <img> without alt, or inline SVG without a name | Add alt, or role="img" and a title |
| It reads out stray words or “group” | An inline SVG with text or titled parts and no role="img" | Add role="img" and a name, or aria-hidden="true" if decorative |
| An unwanted tooltip appears | A <title> in the SVG | Use aria-label, or remove a leftover title from the editor |
| The tooltip says “Layer 1” or a file name | The drawing program wrote the title | Edit or delete it in the code |
title="..." on the <svg> shows no tooltip | SVG has no title attribute | Use a <title> child element |
| A button with an icon is announced only as “button” | Neither the button nor the SVG has a name | aria-label on the button |
| Two SVGs read the same wrong name | Both use the same id for their titles | Make each id unique |
Questions
Does an SVG need alt text? If it carries information, yes, by one of the methods above. If it is decoration, it needs to be hidden instead.
Where does <title> go? First, directly inside the element it names.