( Perceivable / WCAG 1.1.1 )
SVG image has no accessible label
What is this issue?
An inline <svg> element has no accessible name: no <title> child referenced by aria-labelledby, no direct aria-label, and no role="img" pairing with either. <svg> has no alt attribute like <img> does, so its naming mechanism is entirely different, and it’s easy to ship an SVG with visible content but nothing assistive technology can announce.
This applies to inline <svg>...</svg> markup sitting directly in the page’s HTML: a chart built from <path> elements, an icon used as a button’s only content, a logo. An SVG referenced with an <img src="icon.svg"> tag is a different case, covered by the ordinary image-alt rule, since the browser treats that as a regular image with a regular alt attribute.
Why does this matter?
<svg> has no built-in text-alternative mechanism the way <img> does: there’s no alt attribute to fall back on. Without an explicit label, an informative SVG is either skipped silently (the most common outcome) or, depending on the screen reader and browser combination, announced as unhelpful raw markup fragments. Either way, whatever the SVG was drawn to communicate doesn’t reach the user.
A revenue chart rendered as an unlabelled inline SVG shows quarter-over-quarter trends to a sighted user at a glance. A screen reader user reaches the same spot on the page and gets nothing, not even a placeholder announcement telling them content was skipped. An icon-only button built from an SVG with no label is worse: it’s an interactive control with no name at all, so a screen reader user can’t tell what activating it does before they click it.
Who is affected?
- Screen reader users: reach an SVG that’s silently skipped or announced as meaningless markup fragments, losing chart data, diagram content, or the purpose of an icon-only control entirely.
- Low vision users: using a screen reader alongside partial vision get the same silent gap when an SVG’s visual detail (a small trend line, a subtle icon shape) is too fine to make out and no text alternative exists to fall back on.
What users experience
Leila uses NVDA on her Windows laptop to review her team’s quarterly performance dashboard, built from a set of inline SVG bar charts with no titles or labels. NVDA reaches each chart and announces nothing at all: no role, no name, no data. She has no way to tell which region outperformed the others without asking a sighted colleague to read the chart aloud to her, turning a report she should be able to review independently into one she can only access secondhand.
How do I fix it?
For an informative SVG, add a <title> element as its first child and reference it with role="img" plus aria-labelledby pointing at the title’s id. This works because <title> is the SVG specification’s own text-description mechanism, and pairing it with role="img" tells assistive technology to treat the whole graphic as one labelled image instead of trying to parse its internal paths and shapes individually.
For a decorative SVG (a divider, a background flourish, an icon that only repeats text already visible next to it), use aria-hidden="true" instead, so screen readers skip it cleanly rather than announcing something meaningless. Add focusable="false" alongside it too, since older versions of Internet Explorer and Edge make SVGs keyboard-focusable by default even when they carry no interactive role.
Code Examples
<svg viewBox="0 0 400 200">
<!-- chart paths -->
</svg>
<button>
<svg viewBox="0 0 24 24">
<path d="M6 18L18 6M6 6l12 12" />
</svg>
</button><!-- Informative SVG: title + role="img" + aria-labelledby -->
<svg viewBox="0 0 400 200" role="img" aria-labelledby="chart-title">
<title id="chart-title">
Bar chart: Q3 revenue by region. APAC $2.1M, EMEA $1.8M, Americas $3.4M.
</title>
<!-- chart paths -->
</svg>
<!-- Decorative SVG inside a labelled button: aria-hidden, not a second label -->
<button aria-label="Close dialog">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M6 18L18 6M6 6l12 12" />
</svg>
</button>The chart’s <title> gives screen readers the exact same summary a sighted user gets by scanning the bars, without requiring anyone to read raw coordinate data. The button’s SVG is hidden rather than labelled, because the button already carries its own aria-label; labelling the icon a second time would make the screen reader announce the button’s purpose twice in a row.
Common Mistakes
Mistake: “SVGs don’t need labels because they’re code, not an image.” An inline SVG renders as visual content exactly like a raster image does, and needs the same accessible-naming treatment. Skipping this because “it’s not an <img> tag” leaves the same information gap as a missing alt attribute, just on a different element.
Mistake: “A <title> element by itself is enough.” A bare <title> with no role="img" and no aria-labelledby reference works inconsistently across browsers and screen readers: some read it, some ignore it depending on how the SVG is embedded. Pairing role="img" with aria-labelledby pointing at the title’s id is the reliable combination, not the title alone.
Mistake: “The SVG icon inside my labelled button also needs its own aria-label.” If the button already has an accessible name (through aria-label, visible text, or aria-labelledby), the icon inside it should be hidden with aria-hidden="true", not separately labelled. Labelling both makes some screen readers announce the button’s purpose twice.
Mistake: “Complex SVG charts just need a short title, same as a simple icon.” A short <title> is right for a simple icon, but a data-heavy chart needs its key takeaway summarized in the title and the full dataset made available elsewhere (as an adjacent visible table or a linked long description), the same complex-image logic that applies to a detailed raster chart.
How RedFlag Detects This
Automated: axe-core rule, runs on every scan. RedFlag calls axe-core’s svg-img-alt rule as part of every scan, restricted to the WCAG 2.0/2.1/2.2 A and AA rule set. The rule inspects inline <svg> elements that behave as image content (an <svg> carrying an explicit role="img", or a top-level <svg> with no focusable or interactive descendants) and checks whether it resolves a non-empty accessible name through a referenced <title>, aria-label, or aria-labelledby.
False negative: axe-core confirms a name exists; it cannot judge whether the name is accurate or whether a complex chart’s short title adequately summarizes its data. An SVG title reading “Chart” on a detailed revenue breakdown passes the automated check while conveying almost nothing. False positive: an SVG that’s genuinely decorative but happens to lack both aria-hidden="true" and a name can be flagged even when the practical impact is minor, since axe-core can’t judge decorative intent on its own: that judgment call is exactly what the Manual Testing steps below cover. Manual step: confirm every flagged SVG’s actual purpose, and check that informative SVGs have accurate, appropriately concise titles rather than placeholder text.
Manual Testing
- Open the page in Chrome or Firefox with NVDA or VoiceOver running.
- Navigate through the page’s graphics using the screen reader’s element list (NVDA: Insert+F7, filtered to Graphics; VoiceOver: the Rotor, filtered to Images).
- Listen to what’s announced for each inline SVG: an informative one should announce a specific, accurate description; a decorative one should be silent and skipped.
- Tab to any SVG used inside a button or link and confirm only the control’s own name is announced once, not the icon’s description as a separate, duplicate announcement.
- If an SVG announces nothing when it should convey information, or announces raw markup fragments, the check fails.
Related WCAG Success Criteria
1.1.1 Non-text Content: All non-text content must have a text alternative that serves the equivalent purpose. An unlabelled informative SVG fails this criterion directly, since it has visual content with no text equivalent available to assistive technology.
4.1.2 Name, Role, Value: Every interface component must expose a name, role, and value. An SVG used as the only content inside a button or link also fails 4.1.2, since the control itself ends up with no accessible name.
Related Issues
Image is missing alt text is the equivalent failure on a native <img> element instead of an inline SVG: same missing-text-alternative problem, a different element with a different naming mechanism.
role=“img” element has no accessible text covers the sibling case where an icon font, not an SVG, is grouped into a single image using role="img".
Object element has no text alternative and Image input is missing alt text cover the same naming failure on two other non-text element types axe-core checks separately.
Image map area element is missing alt text is the equivalent failure inside a client-side image map’s clickable regions rather than an SVG.
References
- W3C Understanding 1.1.1: Non-text Content
- MDN: title element (SVG)
- W3C Technique ARIA6: Using aria-label to provide labels for objects
Frequently asked questions
Does the alt attribute work on an inline SVG?
No. alt only exists on the HTML img element. An inline svg needs a different naming mechanism entirely: a title element referenced by aria-labelledby, a direct aria-label, or aria-hidden="true" if the svg is decorative.
Does every SVG on a page need a label?
No, only informative ones. A decorative SVG, such as a background flourish or an icon that repeats text already visible next to it, should use aria-hidden="true" so screen readers skip it, not a label describing what it looks like.
Does title alone make an SVG accessible without role="img"?
Not reliably. A title element on its own can work in some browser and screen reader combinations, but pairing it with role="img" and aria-labelledby is the most consistent approach, since it explicitly tells assistive technology to treat the svg as a labelled image rather than leaving the naming path to default browser behavior.
Should an SVG used as a clickable icon inside a button have its own label?
No, and adding one can cause double announcements. If the button itself already has an accessible name, such as aria-label="Close dialog", the SVG inside it should be aria-hidden="true" so only the button label is announced, not the icon description as well.
Does a CSS background-image SVG need this same fix?
No, because it is invisible to this rule and to assistive technology by a completely different route. A CSS background image carries no accessible name at all; if it conveys real information, that information needs to exist as separate visible text or an aria-label on a nearby element.