Back to Learn SVG Animation

Accessible SVG: title, desc, ARIA Labels, and Decorative Icons

By Published Updated education

For accessible SVG, first decide whether the graphic is informative, interactive, or decorative. Then give it one concise accessible name, add a description only when it carries useful detail, and hide decorative SVG from assistive technology.

The short answer: decide whether an SVG is informative, interactive, or decorative before adding ARIA. Informative SVG needs one concise accessible name and, only when useful, a longer description. Decorative SVG should be removed from the accessibility tree. Interactive controls need their own HTML or ARIA name, keyboard behavior, and state.

This guide gives you copyable patterns for inline SVG, SVG image files, icon buttons, and animated graphics. The goal is not to add every accessibility attribute. It is to expose the same purpose and result that a sighted user receives, without duplicate or noisy announcements.

Choose the SVG pattern by purpose

Start with the job the graphic performs. That decision determines whether you need <title>, <desc>, an alt attribute, a visible label, or aria-hidden="true".

Informative inline graphic

  • Use: role="img" plus an accessible name; add a description when it contributes meaningful detail.
  • Avoid: A vague filename or unlabeled paths.

SVG loaded with an image element

  • Use: A useful alt value, or alt="" when decorative.
  • Avoid: Expecting markup inside the SVG file to replace the HTML image alternative.

Decorative inline SVG

  • Use: aria-hidden="true" and keep it out of the focus order.
  • Avoid: Giving ornament a name that adds noise.

Icon inside a button or link

  • Use: Name the control and hide the icon when it repeats that name.
  • Avoid: Making the SVG a second, separately announced image.

Interactive chart or diagram

  • Use: Named controls, keyboard access, programmatic state, and an equivalent summary or data view.
  • Avoid: Treating a complex application as one static image.

The most common failure is not missing ARIA; it is assigning the wrong semantic job. A chevron beside “Next” is decoration because the visible word already names the control. A sparkline that communicates a 17% decline is information because the trend changes the meaning of the page.

Pattern 1: name an informative inline SVG

For a self-contained informative graphic, give the root SVG an image role, connect a short label with aria-labelledby, and connect optional detail with aria-describedby. IDs must be unique on the rendered page, including when a component appears more than once.

<svg
  role="img"
  aria-labelledby="sales-chart-title"
  aria-describedby="sales-chart-desc"
  viewBox="0 0 320 160"
  xmlns="http://www.w3.org/2000/svg">
  <title id="sales-chart-title">Monthly sales trend</title>
  <desc id="sales-chart-desc">
    Sales rose from 42 thousand dollars in January
    to 58 thousand dollars in March.
  </desc>
  <path d="M20 130 L150 92 L300 38" fill="none" stroke="currentColor" />
</svg>

The accessible name answers “What is this?” The description adds information that matters but does not belong in the short name. MDN defines SVG <title> as short text and <desc> as a longer description. The WAI-ARIA guidance makes the same distinction between the concise name referenced by aria-labelledby and the longer description referenced by aria-describedby.

Do not put a paragraph into the accessible name. Long names are hard to navigate and repeat. If the surrounding page already contains a visible heading and summary, reference those instead of maintaining hidden duplicate copy:

<h3 id="trend-heading">Monthly sales trend</h3>
<p id="trend-summary">Sales increased 38% from January to March.</p>

<svg
  role="img"
  aria-labelledby="trend-heading"
  aria-describedby="trend-summary"
  viewBox="0 0 320 160">
  <!-- chart geometry -->
</svg>

Referencing visible text reduces the risk that the visual explanation and the accessible explanation drift apart. The W3C guide to accessible names and descriptions also recommends visible labels when they are available.

Pattern 2: hide truly decorative SVG

A decorative flourish, separator, background shape, or repeated icon adds no information of its own. Hide it from assistive technology and ensure it cannot receive keyboard focus.

<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
  <path d="M5 12h14" />
</svg>

aria-hidden="true" removes the element and its descendants from the accessibility tree; it does not visually hide the SVG. MDN’s aria-hidden reference warns not to use it on a focusable element or an ancestor of focusable content. In other words, never hide a graphic that contains a control users still need to operate.

The same rule applies to an icon that repeats a button’s visible label:

<button type="button">
  <svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
    <path d="M12 4v16M4 12h16" />
  </svg>
  Add item
</button>

Here, “Add item” names the button. Announcing “plus image, Add item” would be redundant. For an icon-only button, keep the SVG hidden but give the button itself a name, such as <button aria-label="Add item">. The control—not its drawing—is the interactive object.

Pattern 3: use alt text when SVG is an image file

When SVG is loaded through an HTML <img> element, use the normal image pattern. Informative images need useful alternative text. Decorative images need an empty alternative so assistive technology can skip them.

<img
  src="quarterly-sales.svg"
  alt="Quarterly sales increased from $1.2M to $1.8M"
  width="640"
  height="320"
>

<img src="wave-divider.svg" alt="" width="1200" height="80">

Write the alternative for the graphic’s purpose in context, not its file format. “Quarterly sales increased…” is useful; “SVG chart image” is not. If the same numbers are immediately available in a table or adjacent sentence, a shorter alternative—or an empty one when the image is fully redundant—may provide a cleaner experience. W3C’s decorative images tutorial explains when an empty alternative is appropriate.

Accessible animation: expose the result, not every frame

An animated SVG usually should not announce every visual change. A logo reveal remains a logo. A loading spinner is normally decorative next to text such as “Uploading file.” A progress graphic should expose its meaningful value through an HTML <progress> element, status text, or a correctly implemented progressbar—not by repeatedly changing the SVG title.

Motion also needs a reduced-motion behavior. Start with a complete static state, then add animation only when the user has not requested less motion:

.status-mark {
  transform: scale(1);
}

@media (prefers-reduced-motion: no-preference) {
  .status-mark {
    animation: confirm-pop 360ms ease-out both;
  }
}

@keyframes confirm-pop {
  from { transform: scale(.8); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}

This progressive pattern leaves the final meaning visible even when animation is unavailable. W3C technique C39 documents using prefers-reduced-motion to suppress non-essential interaction motion. For more implementation options, see how to respect prefers-reduced-motion.

Accessibility attributes do not make animation faster. For performance, keep SVG geometry as simple as the design permits, avoid updating many DOM nodes every frame, and prefer animating transforms or opacity when that produces the required effect. Measure on representative mobile hardware instead of assuming a small file is cheap to render. The practical checks in SVG animation performance best practices help you separate download size, paint cost, and scripting work.

Common mistakes and why they fail

  • Adding both aria-label and aria-labelledby without a reason. The referenced label takes precedence, which can make the inline string misleading or dead maintenance weight.
  • Giving every path a title. Users usually need the meaning of the composed graphic, not a list of drawing primitives. Label individual parts only when they are separately interactive or meaningful.
  • Using the HTML title attribute as the only text alternative. Tooltip behavior is not a dependable replacement for visible text or a deliberate accessible name.
  • Reusing IDs in a component loop. Duplicate title and description IDs can associate an SVG with the wrong text. Generate stable, unique ID prefixes for each instance.
  • Putting aria-hidden="true" on a clickable SVG. The control can remain operable visually while disappearing from the accessibility tree. Put semantics on a real button or link.
  • Updating an ARIA label on every animation frame. Rapid announcements overwhelm users. Communicate important state changes at human-readable milestones.
  • Assuming one pattern works in every embedding mode. Inline SVG, an <img>, CSS background images, and interactive SVG applications have different semantic boundaries.

A practical SVG accessibility test

  1. Turn the graphic off. Can a user still understand the purpose or result from the available text? If not, add an equivalent name, description, data table, or visible summary.
  2. Inspect the accessibility tree. Confirm that informative SVG has the expected role, name, and optional description, while decorative SVG is absent.
  3. Use only the keyboard. Decorative shapes must not receive focus. Every genuine control needs a logical focus order, visible focus, and keyboard operation.
  4. Check repeated components. Search the rendered DOM for duplicate IDs and verify that each SVG references its own label.
  5. Enable reduced motion at operating-system level. Reload the page and confirm that non-essential motion stops while the final information remains available.
  6. Test with the assistive technologies your audience supports. Browser inspection catches structural errors, but a screen reader check catches awkward names, repetition, and reading-order problems.
  7. Measure performance on a realistic page. Test the animation alongside the rest of the interface, not only in an empty demo.

For a broader workflow, pair this checklist with the SVG icon hover guide, especially when an icon changes state on focus or hover.

Quick answers

Does every SVG need role="img"?

No. Use an image role when an inline SVG is functioning as one informative image. Hide decorative SVG. For an interactive visualization, one image role may be insufficient because users need operable controls and exposed state.

Should every SVG contain <title> and <desc>?

No. A title is useful for an informative inline SVG when it provides or participates in the accessible name. A description is useful only when extra detail improves understanding. Decorative SVG should not receive a title merely to satisfy a template.

Is aria-label allowed on SVG?

It can provide a name on an appropriate SVG role, but referenced visible text is often easier to verify and maintain. If both aria-label and aria-labelledby are present, the referenced label wins.

Does aria-hidden="true" hide an SVG visually?

No. It removes the SVG from the accessibility tree while leaving the graphic visible. Use CSS or the HTML hidden attribute when you intend to hide something visually as well.

What is the minimum accessible pattern for animated SVG?

Expose a stable name or status for the meaning, keep decorative frames silent, preserve a complete static end state, and honor prefers-reduced-motion. Then test the rendered result with keyboard access, an accessibility-tree inspector, and the assistive technologies you support.

Sources and further reading

Continue learning
Guide

SVG Animation with the View Transition API: 2026 Guide

Build accessible SVG transitions with the View Transition API. Covers browser support, same- and cross-document patterns, fallbacks, performance, and testing.