Accessible SVG Icons: ARIA, Roles & Screen Reader Best Practices
Learn how to make SVG icons accessible. Understand decorative vs. informative icons, use role='img' with title, aria-hidden for decoration, and aria-label for icon buttons — with tested code patterns.
Why SVG Icon Accessibility Matters
SVG icons are everywhere — navigation menus, buttons, status indicators, feature lists. But without proper accessibility markup, screen reader users experience one of two problems:
- Missing information: The icon conveys meaning (like a warning or a search action), but the screen reader says nothing.
- Noise: The icon is purely decorative, but the screen reader announces the raw SVG markup or an unhelpful "image" label.
Both create a frustrating experience. The fix is straightforward once you understand the patterns.
The First Decision: Decorative or Informative?
Before adding any ARIA attributes, ask one question: Does this icon convey information that isn't available in surrounding text?
Decorative icons add visual interest but carry no unique meaning:
- An icon next to a "Search" label (the label already communicates the action)
- A decorative divider or background pattern
- An icon repeating what adjacent text says
Informative icons carry meaning that would be lost without them:
- A standalone search icon in a button with no visible text
- A warning icon that indicates an error state
- A status icon (checkmark, X) showing success or failure
The pattern you use depends entirely on this distinction.
Pattern 1: Decorative Icons — Hide from Screen Readers
When an icon is purely decorative, hide it from assistive technology completely:
<a href="/search">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 10-.7.7l.27.28v.79l5 4.99L20.49 19l-4.99-5z"/>
</svg>
Search
</a>
aria-hidden="true" removes the SVG entirely from the accessibility tree. The screen reader announces "Search, link" — clean, clear, and without redundancy.
Key points:
- Use
aria-hidden="true"whenever visible text already describes the action - Do not use
role="presentation"— it cancels the native role but doesn't reliably hide content from all screen readers - If the SVG is inside a focusable element, add
focusable="false"to prevent the icon from receiving tab focus in older browsers (notably IE/early Edge)
<button>
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" fill="currentColor">
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
</svg>
Menu
</button>
Pattern 2: Standalone Informative Icons — role="img" + title
When an icon stands alone and conveys meaning, it needs an accessible name. The most reliable pattern across browser/screen reader combinations:
<svg role="img" aria-labelledby="icon-title" viewBox="0 0 24 24" fill="currentColor">
<title id="icon-title">Warning</title>
<path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
</svg>
Why this pattern works:
role="img"tells the browser this is an image (some screen readers skip SVGs without an explicit role)<title>provides the accessible name — it must be the first child element of the<svg>aria-labelledbyconnects the SVG to its title, ensuring screen readers read it consistently
Adding a Description
For icons that need more context, add a <desc> element:
<svg role="img" aria-labelledby="warn-title warn-desc" viewBox="0 0 24 24" fill="currentColor">
<title id="warn-title">Connection error</title>
<desc id="warn-desc">Unable to reach the server. Check your internet connection.</desc>
<path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
</svg>
Screen readers announce: "Connection error. Unable to reach the server. Check your internet connection. Image."
When to use <desc>: Only when the icon communicates something complex that a single title can't convey — like a data visualization or a multi-state indicator. For simple icons, <title> alone is sufficient.
Pattern 3: Icon-Only Buttons — aria-label on the Button
The most common scenario: a button that contains only an icon. Place the accessible name on the button, not the SVG:
<button aria-label="Close dialog">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
</svg>
</button>
Why put aria-label on the button, not the SVG?
- The button is the interactive element — screen reader users navigate by buttons, not by images
- The SVG is an implementation detail of the button's appearance
aria-hidden="true"on the SVG prevents duplicate announcements
Screen readers announce: "Close dialog, button" — exactly what the user needs.
Common Icon Button Examples
<!-- Search button -->
<button aria-label="Search">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 10-.7.7l.27.28v.79l5 4.99L20.49 19l-4.99-5z"/>
</svg>
</button>
<!-- Download button -->
<button aria-label="Download file">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
</svg>
</button>
<!-- Delete button -->
<button aria-label="Delete item">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
</svg>
</button>
Pattern 4: Icons with Visible Text — Let the Text Do the Work
When an icon appears alongside visible text that describes the same action, the icon is decorative:
<button>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
</svg>
Download
</button>
The visible "Download" text serves as both the visual and accessible label. Adding an accessible name to the SVG would cause screen readers to announce "Download image, Download button" — redundant and confusing.
Rule of thumb: If there's visible text, hide the icon. If there's no text, label the icon or its container.
Making AI-Generated Icons Accessible
Icons generated by AI tools (including our AI Icon Generator) come as raw SVG without accessibility attributes. Here's how to add them based on your use case:
For Decorative Use (Icon + Text)
<!-- Generated SVG → Add aria-hidden -->
<a href="/settings">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<!-- AI-generated path data -->
<path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32..."/>
</svg>
Settings
</a>
For Standalone Use (Icon Only)
<!-- Generated SVG → Add role, title, aria-labelledby -->
<svg role="img" aria-labelledby="settings-icon" viewBox="0 0 24 24" fill="currentColor">
<title id="settings-icon">Settings</title>
<!-- AI-generated path data -->
<path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32..."/>
</svg>
For Icon Buttons
<!-- Generated SVG → Wrap in labeled button, hide SVG -->
<button aria-label="Settings">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<!-- AI-generated path data -->
<path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32..."/>
</svg>
</button>
Three-Step Workflow
- Generate your icon with the AI Icon Generator
- Decide if the icon is decorative or informative in your context
- Apply the matching pattern from this guide
Combined with the color techniques from our previous post, you get icons that are both theme-ready and accessible.
Quick Reference
| Scenario | Pattern | Screen Reader Announces |
|---|---|---|
| Icon + visible text | aria-hidden="true" on SVG | The visible text only |
| Standalone icon | role="img" + <title> + aria-labelledby | The title text |
| Icon-only button | aria-label on button, aria-hidden="true" on SVG | The aria-label + "button" |
| Complex icon (chart, diagram) | role="img" + <title> + <desc> + aria-labelledby | Title and description |
| Decorative/ornamental | aria-hidden="true" | Nothing (silent) |
Testing Your Icons
The best way to verify accessibility is to test with actual screen readers:
- macOS: VoiceOver (built-in, activate with Cmd + F5)
- Windows: NVDA (free) or JAWS
- Mobile: VoiceOver (iOS) or TalkBack (Android)
Quick check: navigate through your page with a screen reader. For each icon, confirm:
- Decorative icons are silent
- Informative icons announce a meaningful name
- Icon buttons announce their action + "button"
Related Tools
- AI Icon Generator — Generate SVG icons, then apply these accessibility patterns
- SVG Viewer — Inspect your SVG structure before adding ARIA attributes
- SVG Optimizer — Clean up SVG markup while preserving accessibility attributes