Decorative SVG Issues
Your decorative icons and graphics are being narrated by screen readers like unnecessary commentary. Here's how to silence them.
What is this?
Imagine watching a movie and the narrator describes every detail of the wallpaper pattern in every scene. "The wall has a repeating floral motif in dusty rose with gold accents." You did not ask for that. You just want to follow the plot. That is what happens when decorative SVGs (icons, flourishes, background graphics) are not properly hidden from screen readers. They get announced, adding noise and confusion for visitors who are trying to navigate your actual content.
Decorative images are visuals that add aesthetic value but no information. Think: divider lines, background patterns, icons next to text that already explains the meaning.
Why it matters
- For your visitors: Screen reader users hear every SVG that is not properly hidden. An icon next to the word "Settings" might be announced as "image, settings" — doubling the information. A decorative wave divider might be read as "group" or "image" with no description. Multiply this across a full page and the experience becomes cluttered and disorienting.
- For your business: Excessive screen reader noise makes your site feel unprofessional and hard to use. Visitors will leave for competitors whose sites are cleaner to navigate.
- The standard: WCAG 1.1.1 (Non-text Content) specifies that purely decorative images should be implemented so assistive technology can ignore them. Decorative content should be invisible to screen readers.
<!-- Decorative icon next to text — hide it -->
<button>
<svg aria-hidden="true" focusable="false">
<path d="M12 2L2 7l10 5 10-5-10-5z" />
</svg>
Settings
</button>
<!-- Decorative divider — hide it -->
<svg aria-hidden="true" focusable="false" class="divider">
<line x1="0" y1="0" x2="100%" y2="0" />
</svg><!-- Screen reader announces: "image, settings" or "group, settings" -->
<button>
<svg>
<path d="M12 2L2 7l10 5 10-5-10-5z" />
</svg>
Settings
</button>
<!-- Screen reader announces: "image" or "group" (confusing) -->
<svg class="divider">
<line x1="0" y1="0" x2="100%" y2="0" />
</svg>How to fix it
React / Next.js
When using icon libraries like Lucide React, icons typically need aria-hidden when accompanied by text.
// src/components/nav-link.tsx
import { Settings, Home, Bell } from "lucide-react";
export function NavLinks() {
return (
<nav aria-label="Main navigation">
{/* Icons are decorative here — the text does the talking */}
<a href="/" className="flex items-center gap-2">
<Home className="h-4 w-4" aria-hidden="true" />
<span>Home</span>
</a>
<a href="/settings" className="flex items-center gap-2">
<Settings className="h-4 w-4" aria-hidden="true" />
<span>Settings</span>
</a>
{/* Icon-ONLY button: NOT decorative — needs a label instead */}
<button aria-label="Notifications">
<Bell className="h-5 w-5" aria-hidden="true" />
</button>
</nav>
);
}
// Decorative background SVG
export function WaveDivider() {
return (
<svg
aria-hidden="true"
focusable="false"
className="w-full text-neutral-800"
viewBox="0 0 1440 60"
preserveAspectRatio="none"
>
<path
d="M0,30 C360,60 720,0 1080,30 C1260,45 1350,30 1440,30 L1440,60 L0,60 Z"
fill="currentColor"
/>
</svg>
);
}Plain HTML
<!-- DECORATIVE: icon next to text — hide the icon -->
<a href="/profile">
<svg aria-hidden="true" focusable="false" width="16" height="16">
<circle cx="8" cy="8" r="7" />
</svg>
My Profile
</a>
<!-- DECORATIVE: background shape — hide it completely -->
<svg aria-hidden="true" focusable="false" class="bg-wave">
<path d="..." />
</svg>
<!-- MEANINGFUL: standalone icon conveying information — give it a label -->
<svg role="img" aria-label="Warning: service disruption">
<title>Warning: service disruption</title>
<path d="..." />
</svg>
<!-- MEANINGFUL: logo — give it alt text equivalent -->
<svg role="img" aria-label="Acme Corp logo">
<title>Acme Corp logo</title>
<path d="..." />
</svg>The decision tree is simple:
- Is the SVG purely decorative (dividers, patterns, icons next to text)? Add
aria-hidden="true"andfocusable="false" - Does the SVG convey meaning on its own (warning icon, logo, chart)? Add
role="img"and eitheraria-labelor a<title>element inside the SVG - Is the SVG an icon inside a button with no text? Hide the SVG, label the button
The focusable="false" attribute prevents Internet Explorer and older Edge from adding SVGs to the tab order, which could confuse keyboard users.
Decorative SVGs are not the biggest accessibility problem, but they add up. A page with 20 unhandled icons becomes a noisy mess for screen reader users. The cat expects clean, intentional markup.
How the cat scores this
The cat identifies all SVG elements on the page and classifies them as decorative or meaningful based on context. Decorative SVGs (those adjacent to descriptive text, used as backgrounds, or used as visual dividers) are checked for aria-hidden="true". Meaningful SVGs (standalone icons conveying information) are checked for accessible names via role="img" with aria-label, aria-labelledby, or a <title> element. SVGs that are neither hidden nor labeled get flagged.
Further reading
- CSS-Tricks: Accessible SVGs — the definitive guide to SVG accessibility
- WCAG 1.1.1: Non-text Content — the standard for images and graphics
- Smashing Magazine: Accessible SVG Patterns — comparison of different SVG labeling patterns