SVG image without a text alternative (svg-img-alt)

The svg-img-alt rule flags inline <svg> elements that declare themselves an image – role="img" or a graphics role – but have no accessible name. A screen reader then announces "image" and nothing else. The fix is a <title> as the first child of the SVG, or an aria-label, that says what the graphic means.

What the rule means

Inline SVG has no alt attribute. When a logo, an icon or a chart is drawn as <svg> and marked role="img", its text alternative has to come from somewhere else. axe accepts:

  • a non-empty <title> element that is a direct child of the <svg>,
  • aria-label or aria-labelledby,
  • a title attribute.

The rule checks <svg> elements with the roles img, graphics-document or graphics-symbol. A <title> nested inside a <g>, an empty <title></title> or a <desc> on its own does not count.

Two things it does not see. An SVG without one of those roles is not checked at all – if it carries meaning and has no name, a person has to catch it. And axe cannot tell whether the name is right: <title>icon-cart</title> passes.

Who is affected

Blind people using a screen reader hear "image" where sighted visitors see a company logo, a warning icon or a chart. People with low vision who use a screen reader alongside magnification miss the same information. When the SVG is the only content of a link or button, the control has no name either, and voice-control users cannot say which one they mean.

Why the check fails

  • Icon systems and sprites – <svg role="img"><use href="#icon-cart"></use></svg> – where the role is set in the component and the title is never passed in.
  • Logos pasted from a design tool with role="img" added by hand but no <title>.
  • A <title> in the wrong place, inside a <g> group, or an empty one left behind by an export.
  • Charts and maps rendered as SVG by a library, with the role set and the description left to the developer.
  • Accessibility linters that tell developers to add role="img", followed by nothing else.

How to fix it

  1. If the SVG carries information, add a <title> as its first child and connect it with aria-labelledby – that combination is read reliably across browsers and screen readers.
  2. For an icon inside a button or link, name the control instead and hide the SVG.
  3. If the SVG is decoration, drop the role and add aria-hidden="true" and focusable="false".
<!-- Before: an SVG logo announced only as "image" -->
<a class="site-logo" href="/">
  <svg role="img" viewBox="0 0 24 24" width="48" height="48">
    <path d="M12 2 2 22h20z" fill="#1d4ed8"/>
  </svg>
</a>
<!-- After: a title as first child, referenced by aria-labelledby -->
<a class="site-logo" href="/">
  <svg role="img" aria-labelledby="logo-title" viewBox="0 0 24 24" width="48" height="48">
    <title id="logo-title">Example Ltd – home</title>
    <path d="M12 2 2 22h20z" fill="#1d4ed8"/>
  </svg>
</a>

A decorative icon next to visible text is hidden; the button is named by its text:

<button type="button" class="btn-cart">
  <svg aria-hidden="true" focusable="false" width="16" height="16"><use href="#icon-cart"></use></svg>
  Basket
</button>

How to test it manually

  1. Search the Elements panel for <svg and note which have a role.
  2. Select each and read the "Name" row in the Accessibility pane (Chrome, Edge) or Firefox's accessibility inspector.
  3. Check the SVGs without a role too: does any of them convey something – a status, a chart, a logo link – that has no name? This rule will not find those.
  4. Listen with NVDA or VoiceOver: informative graphics should be announced with their meaning, decorative ones not at all.

1.1.1 Non-text Content, Level A. Related: 4.1.2 Name, Role, Value when the SVG is the only content of a button or link, and 1.4.11 Non-text Contrast for icons that have to be seen to be understood.

How Reviseberg reports it

Reviseberg runs svg-img-alt on every crawled page at 1280px. The issue list shows the rule with its severity, WCAG criterion and level, the number of SVGs and pages affected, and the points you get back by fixing it. A logo or icon component in the header produces one finding per page, so the detail view – CSS selector, HTML snippet, every affected page – usually leads straight to a single component.

You can mark a finding as "ignore", "can't fix" or "false positive" with a reason; every decision is logged. A clean result never marks 1.1.1 as passed on its own: SVGs without a role and names that are present but wrong are for a person to check.

  • undefined – the same problem on HTML elements with role="img".
  • undefined – <img> elements, including SVG files loaded with <img src="….svg">.
  • undefined – a link whose only content is an unnamed SVG.
  • undefined – an icon button with no accessible name.

Check your icons and logos for text alternatives – get a free scan

Frequently asked questions

Is a <title> inside the SVG enough?

For this rule, yes – as long as it is a direct child and not empty. Adding aria-labelledby pointing to it makes the name more dependable across browser and screen reader combinations.

What about SVG files in an <img> tag?

Those are ordinary images: they need an alt attribute and are checked by image-alt, not by this rule.

Do I need <desc> as well?

Only for graphics that need a longer description, such as a chart. <desc> on its own does not give the SVG a name.

Sources

  1. W3C, Understanding SC 1.1.1 Non-text Content – https://www.w3.org/WAI/WCAG22/Understanding/non-text-content
  2. Deque University, axe-core 4.13 rule svg-img-alt – https://dequeuniversity.com/rules/axe/4.13/svg-img-alt
  3. W3C, WAI-ARIA Graphics Module 1.0 – https://www.w3.org/TR/graphics-aria-1.0/
  4. MDN, SVG <title> element – https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title

See what a scan finds on your site

One page in about thirty seconds, no email needed. The full report covers up to 100 pages and a keyboard journey.