Accessible SVG Icons

By the Axialis Engineering team ·

Accessible SVG Icons

An inline SVG icon ships with no accessible name by default: screen readers either skip an informative icon entirely or read decorative ornaments as noise. This reference shows the exact markup that fixes both cases — aria-hidden to hide decoration, role="img" with <title>/<desc> or aria-label to name meaning — plus how to export a clean, currentColor SVG from IconVectors that drops straight into this markup.

Decorative vs informative icons

Decision tree: which pattern do I use?

Walk these questions in order and stop at the first match:

  1. Is the icon inside an interactive control (button or link) with no visible text? Put the name on the control with aria-label and hide the icon (Pattern 3 below).
  2. Does adjacent visible text already convey the meaning? The icon is decorative: add aria-hidden="true" (Pattern 1).
  3. Does the icon carry meaning written nowhere else (a status, a rating, a standalone warning)? Expose it with role="img" and a short label (Pattern 2).
  4. Is it purely visual ornament? Hide it (Pattern 1).

Rule of thumb: name it once. If the control or nearby text already names it, hide the icon so a screen reader does not repeat it.

Export a clean, themable SVG from IconVectors

  1. Open or create your icon:
    • File → Open… (Ctrl+O) or New Icon (Ctrl+N).
    • Prefer a simple path-based icon; set fills/strokes to currentColor for easy theming.
    A single-path camera icon open on the IconVectors canvas, ready to export as a minified SVG
    Export a minified SVG via File → Export → Export Minified (Shift+Ctrl+M). Use View → Source Code (F3) to verify viewBox and currentColor.

Pattern 1 — Decorative SVG (hide from AT)

For purely visual icons, remove them from the accessibility tree so screen readers don't announce noise.

<!-- Decorative icon next to text -->
<p>
  <svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 24 24">
    <path d="M4 12 9 17 20 6" fill="none" stroke="currentColor" stroke-width="2"/>
  </svg>
  Settings updated
</p>

Pattern 2 — Informative inline SVG with role & label

When the icon conveys meaning, give it an accessible name (short) and an optional long description.

<!-- Informative icon announced as "Warning" -->
<svg role="img" aria-labelledby="warn-title warn-desc" width="20" height="20"
     viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <title id="warn-title">Warning</title>
  <desc id="warn-desc">Triangle with exclamation mark</desc>
  <path d="M12 3 2 21h20L12 3zm0 6v6m0 4h.01" fill="none" stroke="currentColor" stroke-width="2"/>
</svg>

Pattern 3 — Icon-only buttons/links

Interactive controls need an accessible name. Put the label on the button/link and hide the icon.

<button type="button" aria-label="Close dialog" class="icon-btn">
  <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 24 24">
    <path d="M6 6 18 18M6 18 18 6" fill="none" stroke="currentColor" stroke-width="2"/>
  </svg>
</button>

Pattern 4 — External SVG files via <img>

When using <img src="icon.svg">, supply the meaning using alt. Use an empty alt for decorative images.

<!-- Informative: announced as "Download" -->
<img src="/icons/download.svg" width="20" height="20" alt="Download">

<!-- Decorative: ignored by AT -->
<img src="/icons/starburst.svg" width="20" height="20" alt="">

Pattern 5 — SVG sprites with <use>

For sprite references, the <svg> wrapper gets the ARIA.

<!-- Decorative sprite use -->
<svg aria-hidden="true" focusable="false" class="icon"><use href="#icon-check" /></svg>

<!-- Informative sprite use -->
<svg role="img" aria-label="New notifications" class="icon"><use href="#icon-bell" /></svg>

Keyboard focus rules (quick recap)

Implementation checklist

Quick testing checklist

Related guides

Start Making SVG Icons Today with IconVectors

Download the fully-functional 30‑Day Free Trial and unlock your icon design workflow.

Version 1.70 for Windows, macOS, and Linux