SVG Accessibility: A Practical Guide for Developers
SVG is the most accessible image format on the web — when it’s done right. Done wrong, it’s a black hole that screen readers either ignore completely or read out as a wall of useless geometry. Most SVGs in production sit in that black hole because the defaults aren’t great and the rules are scattered across half a dozen specs. This is the consolidated version.
Three categories of SVG
Every SVG on a page falls into one of three buckets. The accessibility treatment is different for each, and choosing the wrong bucket is the most common mistake.
- Decorative. The image conveys no information that isn’t already in the surrounding text. A magnifying glass icon next to the word “Search” is decorative — the word already tells the user what the button does.
- Informative. The image conveys information not present in surrounding text. An icon-only button with no visible label is informative — without the icon, the user wouldn’t know what the button does.
- Complex. Charts, diagrams, infographics, and maps. These need structured descriptions, not a single label.
Decorative SVG
The goal is to make the image invisible to assistive technology. Two things to do:
<!-- Inline SVG -->
<svg aria-hidden="true" focusable="false" ...>
<path d="..." />
</svg>
<!-- External SVG via <img> -->
<img src="/icons/checkmark.svg" alt="" role="presentation" />The aria-hidden="true" attribute removes the SVG from the accessibility tree entirely. The focusable="false" attribute is critical for inline SVG: in older Internet Explorer and some keyboard-navigation modes, inline SVGs are tab-stoppable by default. You almost never want that for a decorative icon.
For an external SVG, an empty alt="" attribute (combined with role="presentation" as belt-and-suspenders) tells screen readers to skip it. Empty alt is not the same as missing alt — missing alt often makes screen readers read the file path out loud.
Informative SVG
The image conveys meaning. The screen reader needs to communicate that meaning. The recommended approach uses role="img" plus a label:
<svg
role="img"
aria-label="Download invoice"
focusable="false"
viewBox="0 0 24 24"
>
<path d="M12 3v12m0 0l-4-4m4 4l4-4M5 21h14" />
</svg>The role="img" attribute tells assistive technology to treat the SVG as an atomic image rather than descending into the path data. Without it, some screen readers read out every <path> and <rect> as a separate element, which is exactly as useful as it sounds.
For longer descriptions, prefer the inline <title> element:
<svg role="img" aria-labelledby="chart-title" focusable="false">
<title id="chart-title">Quarterly revenue, Q1 2024 through Q4 2026</title>
...
</svg>The <title> must be the first child of the SVG to be announced reliably. Some browsers also expose it as a tooltip on hover, which is a bonus for sighted users — but don’t rely on it as a UI affordance, because mobile users won’t see hover.
Complex SVG: charts, diagrams, infographics
A bar chart with twelve values cannot be summarized in a single aria-label. For complex SVGs, combine three things:
- A short
<title>for the high-level concept - A longer
<desc>for the detailed description - An accessible data table or list nearby (visible or visually hidden)
<svg role="img" aria-labelledby="t1" aria-describedby="d1" focusable="false">
<title id="t1">Page load times by browser</title>
<desc id="d1">
Bar chart comparing average page load time in seconds across four browsers
on a 4G connection. Chrome 1.2 s, Firefox 1.4 s, Safari 1.1 s, Edge 1.3 s.
</desc>
...
</svg>For interactive charts, also expose the underlying data in a real <table>. Hide it visually with a .sr-only class if you need to keep the visual layout clean — screen readers and keyboard users will still find it. This pattern is standardized in the W3C’s Complex Images tutorial.
The focusable attribute trap
Inline SVGs without an explicit focusable="false" attribute can appear in the keyboard tab order in Internet Explorer 9–11, and the behavior is inconsistent across other browsers. Even though IE is gone, the attribute is still the documented way to opt out, and SVGO’s default config preserves it for exactly this reason.
Rule of thumb: every inline SVG icon should have focusable="false" unless it’s the only interactive content of an actual button or link, in which case the parent element handles focus.
Color contrast — the silent killer
Icons are visual UI affordances, and that means they need to meet the WCAG 1.4.11 Non-text Contrast requirement: a minimum contrast ratio of 3:1 against the adjacent background. A light grey hamburger icon on a white header is the most common WCAG failure on the web.
A few practical guidelines:
- For icons that are part of UI controls (buttons, links, form elements), test contrast against the actual background you put them on.
- For decorative icons accompanied by text, the icon itself doesn’t need to meet contrast — the text does.
- Hover and focus states must also meet contrast against their background.
- If you tint icons via CSS
fillorcolorwithcurrentColor, you can theme contrast at a single CSS variable.
Interactive SVG (clickable shapes, hover states)
SVG can be more than just an image — individual shapes can be focusable, clickable, and react to keyboard events. The accessibility cost goes up sharply.
For a clickable SVG (the entire SVG is one button):
<button onClick={handleClick} aria-label="Close dialog">
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
<path d="M18 6L6 18M6 6l12 12" />
</svg>
</button>The button handles focus, the keyboard activation, and the accessible name. The SVG inside is decorative — the button label tells the screen reader what activating it does. Wrapping a clickable SVG in a real <button> element is almost always easier than reimplementing button semantics on the SVG itself.
For SVG with multiple interactive regions (a clickable map, a chart with hoverable segments), each interactive shape needs tabindex="0", role="button" or role="link", an accessible name, and keyboard handlers for both Enter and Space. This is genuinely complex; if you’re building something like this, lean on a tested library (D3 with the right ARIA wrappers, Highcharts Accessibility, etc.) rather than rolling your own.
Inline SVG vs <img> for accessibility
Inline SVG is more accessible by default because the browser can expose the internal structure (titles, descriptions, individual shapes if needed) to assistive technology. External SVG loaded via <img> is treated as a single opaque image — you only get the alt attribute.
For icons and decorative shapes, both work fine and the choice comes down to caching and bundle size — see inline vs external SVG. For charts and diagrams, inline SVG is essentially required.
How SVGO affects accessibility
The default SVGO configuration is accessibility-safe in 2026, but a few presets are dangerous. If you write a custom SVGO config, double-check these plugins:
- removeTitle — disabled by default, and it should stay that way. This plugin removes
<title>elements which are the primary way SVGs are labeled. - removeDesc — same story for
<desc>elements. - removeUselessStrokeAndFill — usually fine, but can occasionally change which colors are visible and break a contrast assumption you made elsewhere.
- removeViewBox — must be disabled. Removing
viewBoxbreaks the SVG’s ability to scale, which breaks accessibility at every zoom level above 100%.
The svg.dog optimizer uses an a11y-safe SVGO configuration by default — titles, descriptions, ARIA attributes, and viewBox are all preserved. See the SVGO guide for how to verify your own config does the same.
A 60-second accessibility audit
For each SVG on a page, ask:
- Does this image add information not in the surrounding text? If no:
aria-hidden="true"+focusable="false". Done. - If yes: does it have
role="img"and eitheraria-labelor a<title>? - Does the SVG meet 3:1 contrast against its background?
- If it’s clickable, is it wrapped in a real
<button>or<a>? - If it’s a chart, is the data also available as text or a table?
That’s the entire WCAG 2.2 AA story for SVGs in five questions. Run it on the top ten SVGs on your homepage and you’ll fix more accessibility issues than most consultants would in a paid audit.
Related reading
For more on choosing the right SVG delivery method, see inline vs external SVG. For performance trade-offs, see SVG and web performance. And for keeping SVGO from undoing any of the above, see the complete SVGO guide.
Optimize SVGs instantly — no setup needed
500 free optimizations per month. No credit card required.
Get a free API key →