AccessScanRun a free scan

Guide

How to Build Accessible SVG Icons: Decorative vs Informative

SVG icons are everywhere in modern interfaces, yet they are one of the most consistently mishandled elements for accessibility. The same markup can be invisible to a screen reader, read as a string of meaningless node names, or announce a label that contradicts the button it sits in, all depending on a single attribute.

This guide walks through one decision and the attributes that follow from it: when to hide an icon with aria-hidden, when to name it with title and role="img", and how to label icon-only buttons so they are not announced as an unlabeled control. Every pattern maps to a WCAG 2.2 success criterion and works across current screen readers.

Decorative vs informative: the only question that matters

Before writing a single attribute, classify the icon. A decorative icon adds visual flavor but no information the user would miss if it were gone: the magnifying glass next to the visible word "Search", a chevron beside a link that already reads "View pricing". An informative icon carries meaning that exists nowhere else in the surrounding text: a standalone trash-can button, a red triangle that means "validation error", a status dot that means "online".

The test is simple. If you deleted the icon and replaced it with nothing, would a sighted user lose information? If no, it is decorative and should be hidden from assistive technology. If yes, it is informative and needs an accessible name. Most icons in a typical UI are decorative because they sit next to a text label. The mistake is treating every icon as either always-labeled or always-ignored instead of deciding case by case.

Getting this classification right is also what keeps testing clean. Confirm how each icon is exposed by running the page through AccessScan's free checker and by testing with a screen reader, which together catch both the hidden-but-should-be-named case and the labeled-but-redundant case.

Hiding decorative SVGs with aria-hidden

For a decorative inline SVG, remove it from the accessibility tree entirely. SVG has no alt attribute, so the tool is aria-hidden:

<a href="/search"><svg aria-hidden="true" focusable="false" width="16" height="16">...</svg> Search</a>

Two attributes do the work. aria-hidden="true" hides the graphic and all its descendants, so the link announces as "Search" rather than "Search, image". focusable="false" prevents a legacy Internet Explorer and Edge bug where inline SVGs could receive keyboard focus and create phantom tab stops; it is harmless elsewhere and worth keeping as a habit on every inline icon.

If you load the SVG as an image instead of inlining it, use an empty alt to achieve the same result: <img src="/chevron.svg" alt="">. An empty (not missing) alt tells the screen reader to skip the image. Omitting alt entirely is a failure, because many screen readers then fall back to reading the file name, so the user hears "chevron dot s v g".

Naming informative SVGs with title and role=img

When an inline SVG conveys meaning on its own, give it an accessible name. The most robust pattern combines role="img", a <title>, and an explicit association:

<svg role="img" aria-labelledby="warn-title" width="20" height="20"><title id="warn-title">Warning</title>...</svg>

Why each piece is there

  • role="img" tells assistive technology to treat the SVG as a single graphic with a name instead of walking into its <path> and <g> children. Without it, some browser and screen reader pairs expose nothing, and others read raw shape data.
  • <title> is the SVG-native accessible name. Unlike the HTML title attribute (which only produces a tooltip), the SVG <title> element is part of the accessibility tree. It must be the first child of the element it names.
  • aria-labelledby pointing at the title's id makes the association explicit and reliable. Some older screen readers do not pick up a bare <title>, so wiring it with aria-labelledby (or using aria-label directly) removes the ambiguity.

A simpler equivalent is <svg role="img" aria-label="Warning">, which skips the <title> element. Prefer aria-label when the name is short and static; prefer <title> with aria-labelledby when you also want a native SVG tooltip or when a component already renders a title node. Do not set both an aria-label and a <title> with different text: aria-label wins, and the mismatch is usually a copy-paste bug.

Accessible names for icon-only buttons

The single most common icon accessibility failure is the icon-only button: a control whose entire visible content is an SVG with no text. A close button, a hamburger menu, a "favorite" heart. With nothing but a graphic inside, the button's accessible name is empty, and a screen reader announces "button" with no indication of what it does.

The fix has two halves that must work together. Name the button, and hide the icon:

<button aria-label="Close dialog"><svg aria-hidden="true" focusable="false">...</svg></button>

The accessible name lives on the interactive element, which is where assistive technology and voice-control software look for it. The SVG is hidden so it cannot inject a competing name or read as a second thing. Putting the label on the button also means speech users can say "click Close dialog" and have it work.

Two further rules keep these buttons compliant. First, the visible icon must meet 3:1 non-text contrast against its background under WCAG 1.4.11, since the glyph is the only thing communicating the control's purpose; verify it with a contrast checker. Second, the clickable target must be at least 24 by 24 CSS pixels to satisfy WCAG 2.2's new 2.5.8 Target Size (Minimum) at Level AA, so a 16-pixel glyph needs padding around it.

Where this fits in compliance

Accessible icons are not a stylistic nicety. Under the European Accessibility Act, whose requirements apply from 28 June 2025, the technical baseline is WCAG 2.2 Level A and AA as expressed through EN 301 549. Icons touch several criteria at once: 1.1.1 Non-text Content (every informative graphic needs a text alternative), 1.4.11 Non-text Contrast, 2.5.8 Target Size (Minimum), and 4.1.2 Name, Role, Value for any icon that is also a control.

The good news is that the rules form a short, repeatable checklist. Decide decorative or informative; hide the decorative ones; name the informative ones; and for icon buttons, name the button and hide the icon. Then confirm the names with a screen reader, and use the accessibility checklist to make sure icons are not the gap in an otherwise conformant page.

Check your site against AccessScan

See your issues ranked by impact in seconds — free.

Run a free accessibility scan

FAQ

Should I use aria-hidden or an empty alt on an inline SVG?

Inline SVGs do not have an alt attribute, so aria-hidden="true" is the way to hide a purely decorative inline SVG. The empty-alt technique (alt="") applies to <img> elements, including an SVG loaded with <img src="icon.svg" alt="">. Both correctly remove the graphic from the accessibility tree; pick the one that matches how the SVG is embedded.

Does role="img" go on the SVG or on a wrapper element?

Put role="img" directly on the <svg> element that carries the accessible name. Adding role="img" normalizes how browsers and screen readers expose the SVG, because some older combinations otherwise ignore the graphic or read its raw child nodes. Pair it with aria-label or aria-labelledby pointing at a <title>.

Why does my icon button read as 'button' with no label?

An icon-only <button> with just an SVG inside has no text node, so the accessible name is empty. Add the name with aria-label on the button (aria-label="Search") and hide the inner SVG with aria-hidden="true" so its title does not collide with or duplicate the button label.

Do decorative icons need to meet color contrast requirements?

No. WCAG 1.4.11 Non-text Contrast applies to graphics needed to understand content and to UI component states, not to purely decorative imagery. A decorative icon hidden with aria-hidden has no informational role, so it is exempt. Any icon that conveys meaning or status, such as an error glyph, must meet the 3:1 contrast ratio.

Does an icon button need to satisfy the WCAG 2.2 target size rule?

Yes. WCAG 2.2 added 2.5.8 Target Size (Minimum) at Level AA, requiring interactive targets to be at least 24 by 24 CSS pixels (with spacing and other exceptions). A 16-pixel icon glyph inside a button needs enough padding to reach that hit area, which also helps users with motor impairments and touchscreen users.

More guides