Getting an accessible SVG mostly comes down to deciding what the graphic is for before you touch any markup. A graphic that carries meaning needs role=”img” and a text name, and pure decoration should be hidden from assistive technology altogether. Clickable ones are the odd case. Put them inside a native button or link and let that control hold the label.
Browsers expose little about an SVG on their own, so the name, role and description come from the author, usually through ARIA attributes. That has a cost. WebAIM’s 2026 analysis of one million home pages found 59.1 detected errors per page on pages using ARIA against 42 on pages without it, and WebAIM links the gap in part to page complexity.
Which Treatment Does Each Type of SVG Need?
Sort the graphic first and the markup mostly follows. A graphic that means something needs a text name. Decoration should disappear from the accessibility tree, and anything interactive belongs in a native control that has a label.
The W3C’s SVG Accessibility API Mappings draft (Working Draft, 24 September 2026) describes most SVG elements as low-level drawing instructions. They mean nothing to assistive technology until the author adds alternative text or ARIA attributes.
It’s still a draft, so treat it as direction and not as a promise about how browsers behave.
| SVG type | Markup pattern | What a screen reader announces |
|---|---|---|
| Informative icon or illustration | Inline svg with role=”img” and a title referenced by aria-labelledby | The name, then the image role |
| Decorative shape or flourish | aria-hidden=”true” on inline svg, or alt=”” on an img element | Nothing |
| Chart or diagram | role=”img”, title and desc, plus visible text or a data table | Name and description, then the visible text |
| Icon button or icon link | Native button or link with the name on the control and the svg hidden inside | The control name and its role |
Informative SVGs
Put role="img" on the svg element and give it a short name. Inline SVG graphics are plain markup, and without the role each shape can show up as its own item.
How bad does that get? TPGi’s 2013 research, commissioned by Adobe, found the SVG version of the HTML5 logo exposed as a container image holding 10 nested images.
The role fixes that. The SVG-AAM draft notes that the img role excludes child content from the accessibility tree, so one graphic reads as one image.
Decorative SVGs
WCAG 1.1.1 requires pure decoration to be built so assistive technology can ignore it (W3C Understanding docs, updated September 2026).
- For inline SVG, add aria-hidden=”true” to the svg element.
- An img element takes alt=”” and no title attribute (WCAG technique H67).
A CSS background is fine for decoration. For anything that carries meaning it’s a documented failure (failure F3).
Context decides the category. An icon beside a visible text label is decorative in that spot, and the same icon alone in a toolbar is not.
How to Give an SVG an Accessible Name
Start with role=”img” on the inline svg. Put a title element first inside it and point aria-labelledby at the title’s id. Smashing Magazine ran a May 2021 comparison of 12 SVG markup patterns across operating system, browser and screen reader combinations, and this pairing landed in its best group.
- Add
role="img"to the svg element. - Insert a
<title>as the first child of the svg (MDN’s placement advice) and give it a unique id. - Add
aria-labelledbyto the svg, set to that id. - Write the title text for the graphic’s job on this page, not for its shape.
- Search the page for duplicate ids before shipping.
<svg role="img" aria-labelledby="dot-title" viewBox="0 0 24 24">
<title id="dot-title">Unread messages</title>
<circle cx="12" cy="12" r="10"/>
</svg>Choosing between title, aria-label and aria-labelledby
A title with no role and no aria-labelledby is the weak option. TPGi’s 2013 test found title and desc ignored in nearly every browser and screen reader pair. Only Internet Explorer 10 with JAWS 15 announced them reliably, and NVDA 2013.2 with Internet Explorer 10 did so only partially and erratically. Adding role=”img” and aria-labelledby produced announcements in most pairs.
That test is old (Internet Explorer 10, Firefox 25, Chrome 30), and it never tried role=”img” with a title alone. Smashing’s 2021 test did (pattern 5) and rated it “Best in Show” among the basic inline patterns. The two studies also overlap on one pattern, and role=”img” with aria-labelledby worked in both.
A title child travels with the SVG file, though browsers may also show it as a tooltip (MDN). The aria-label attribute sets the name directly on the svg with no child markup, and the SVG-AAM draft counts a non-empty aria-label as a reason to expose the element.
For aria-labelledby, point it at the title id or at any visible text. MDN recommends the visible-text route whenever the text can label the graphic.
What the name should say
Name what the graphic does on this page, not what it looks like. W3C’s guidance for WCAG 1.1.1 has one world image that is linked as “International Travel” on a travel site and “International Campuses” on a university site.
File names and placeholder text fail the criterion (failure F30), so “icon-star.svg” is not a name. Deque also advises dropping “image of” and “graphic of”, since the role is announced anyway.
Describing Complex SVG Graphics
A chart or diagram needs a short name plus a long description that carries the same information the picture does. WCAG 1.1.1 (Situation B) requires both when a short text cannot serve the same purpose. Its bar chart example names the chart type and summarizes the trends, then supplies the data in a table where practical.
Inside the SVG, add a desc element after the title and give each its own id. List both ids in aria-labelledby. Keep the description to plain text, because the SVG-AAM draft (issue 6) says desc content is exposed as plain text and not as navigable structure.
Once the description needs lists or tables, a visible paragraph or data table next to the SVG is the better home, with the SVG’s name pointing to it. It also helps readers with cognitive disabilities, who gain from information on screen instead of buried in SVG code (Smashing Magazine, 2021).
MDN’s own example lists the title and desc ids together in aria-labelledby. TPGi’s 2013 research avoided aria-describedby for the description because of support problems.
Smashing’s 2021 results agree. The title, desc and aria-labelledby pattern was the best of its group even though it repeated the description, while the patterns that paired title and desc without aria-labelledby earned a “use caution” rating because some elements were ignored.
Text inside the graphic needs one more decision. Once the svg carries role=”img”, labels set with SVG text elements stop being separate stops for the reader (SVG-AAM draft), so axis labels and values must also appear in the description or beside the chart.
Which Embedding Method Keeps an SVG Accessible?
Inline SVG gives you the most control. An img element is enough when one alt string does the job, and CSS backgrounds belong to decoration only. My rule is to use img until you need desc, per-element focus or CSS styling of the internals, and then switch to inline.
| Method | Where the name lives | Best use | Main limit |
|---|---|---|---|
| Inline svg | title, aria-label or aria-labelledby | Informative, complex and interactive graphics | Adds to HTML weight |
| img element | alt attribute | Simple logos and icons | Internals cannot be styled or exposed |
| object element | Fallback content in the object body | External files that need fallback text | Little tested support data, so test first |
| CSS background | None possible | Pure decoration | Fails WCAG 1.1.1 for meaningful images |
The object row rests on WCAG technique H53 and the matching W3C test rule, which require a non-empty name. None of the browser and screen reader comparisons cited here covers object, so check it against your own screen reader pairs.
Inline SVG
Every naming pattern from the previous sections works here, and per-element focus and styling come through the page’s CSS. MDN’s guide to embedding SVG in HTML shows the minimal accessible version.
The downside is repetition. The markup repeats on every page that uses it, and Smashing notes the extra code can slow loading slightly. Each copy also needs its own title id.
SVG in an img element
Smashing’s 2021 tests rated img with alt alone “not recommended”, while img with role=”img” plus alt or aria-label landed in the best group. The article gives no reason, so test your own browser and screen reader pair before standardizing on either.
Pages stay lighter and one file gets reused everywhere. What you give up is control over visual elements and animation, plus any internal title or desc.
For a plain logo, img with role=”img” and a meaningful alt is the sensible default.
Making Interactive SVG Keyboard Accessible
Wrap the SVG in a native button or link and name that control, because browsers already handle focus, Enter and Space for those elements. Reserve tabindex for graphics where individual SVG shapes must take focus themselves.
SVG 2 added keyboard navigation modeled on the HTML tabindex approach, so links and elements with a tabindex receive sequential focus (SVG-AAM draft). Focusable elements always reach the accessibility tree, even when marked presentational.
Icon buttons and links
WebAIM’s 2026 analysis of one million home pages found that one in four linked images had no alternative text, which leaves the link without a name.
Put the name on the control, through visible text, aria-label or visually hidden text, and mark the svg inside as aria-hidden=”true” so the name isn’t read twice. Describe the purpose, such as “Close menu” and not “X” (WCAG 1.1.1, Situation C).
Custom interactive graphics
Seat maps and floor plans are the cases where the graphic is the interface. Native controls first, since custom SVG widgets cost more script and more testing.
- Put
tabindex="0"on each SVG element that takes focus, in the order readers expect. - Every focusable element needs a role and a name.
- role=”button” adds semantics only, so Enter and Space handling is still script work.
- Never add aria-hidden to something focusable. The attribute sends a conflicting signal, and the SVG-AAM draft keeps focusable elements in the tree regardless.
- If you style the focus indicator yourself, it needs a 3:1 contrast ratio against adjacent colors (W3C Understanding SC 1.4.11, updated September 2026). Stripping outlines is a documented failure (F78).
Contrast, Color and Forced Colors in SVG
The meaningful shapes in an SVG have to contrast with their background, and meaning can’t rest on hue alone. The graphic also has to stay readable in forced colors mode. Each rule treats the graphic as a set of parts, so the real question is which parts carry the message.
Contrast and color cues
W3C’s failing example for non-text contrast pairs a pale yellow (#FFF000) with white, a ratio of 1.2:1. The threshold from the focus indicator rule carries over to graphics. Parts needed to understand the content reach 3:1 against adjacent colors, and pure ornament is exempt (W3C, Understanding SC 1.4.11).
Text inside the graphic falls under the regular text contrast minimum (SC 1.4.3).
Some things pass without extra work. Labels and values written as visible text on the chart free the slices or bars from carrying the message alone, and the same data in a table after the graphic does the same job.
Others need a fix. Pie slices separated only by fill do (W3C’s passing pie chart adds a darker border around its yellow slice), and so do status icons with no text next to them and series that differ by hue alone.
Check each fill and stroke pair against its neighbor with a color contrast tool before the graphic ships.
When brand colors fail the check, an accessible color palette generator can supply replacement pairs.
Hue alone is also a Use of Color problem (SC 1.4.1). W3C’s SVG example is a chemical compound diagram whose elements are marked by color and by a number, with a legend for both, so readers who cannot separate the colors still read the numbers.
Two hues that also differ enough in lightness to reach 3:1 count as an extra cue, W3C adds. A green outline for valid and a red one for invalid still needs a second indicator.
Forced colors mode
Forced colors mode, with Windows High Contrast as the standard example, replaces author colors with a palette the user chose, and SVG fill and stroke are among the properties it overrides (MDN, Baseline since September 2022).
Shadows go first. box-shadow and text-shadow are forced to none, so a shadow can’t be the only edge of an icon. Background images that aren’t url-based get the same treatment, which takes out gradients.
Color is forced too, which is good news for icons that take their fill from currentColor, since they stay in step with the surrounding text. One catch is that system colors follow native element semantics. A role=”button” on a div or an svg does not earn ButtonText, while a native button does (MDN).
The escape hatch is forced-color-adjust: none on a single element, which also switches off the text backplate. MDN advises small, targeted tweaks and warns against building a separate design for this mode, because the reduced palette is often what makes a page readable for these users.
Handling Animated SVG and Reduced Motion
WCAG 2.2.2 wants a way to pause, stop or hide an animated SVG when it starts automatically and runs for more than five seconds next to other content. Visitors who asked their device for less motion need it toned down as well.
W3C chose five seconds as long enough to get attention and short enough for a user to wait out the distraction.
Meeting the pause requirement
- “Starts automatically” includes motion set off by hover, focus or scrolling into view, which can also fail SC 2.3.3 Animation from Interactions.
- A loading animation that is the only content on the page is exempt, since nothing is presented in parallel with it.
- The control cannot tie up focus. An animation that stops only while it holds focus fails.
- One shared control for several animations is the better experience, though separate controls still pass.
SMIL animation (animate, animateTransform, animateMotion) sits inside the SVG, and calling pauseAnimations() on the svg element suspends its animation clock (MDN).
Motion written in CSS, as in this guide to animating SVG with CSS, pauses through animation-play-state instead.
Honoring reduced motion
The prefers-reduced-motion feature has worked across browsers since January 2020, according to MDN’s Baseline data.
It takes two values, no-preference and reduce. Scaling or panning large objects are the usual vestibular triggers, and MDN’s own example swaps a pulsing scale for a slow dissolve.
Because the feature is one of the media queries in CSS, the calmer fallback can live in the same stylesheet as the animation it replaces.
SMIL timing lives in element attributes, which a CSS media query cannot reach. Read the preference in script with matchMedia and call pauseAnimations() when it returns reduce.
For new work I’d go with CSS animation. It’s the easier path to respectful motion.
How to Test an Accessible SVG
Lint while you author, run an automated rule on the rendered page, then listen to the graphic in a screen reader. Each of those catches things the others miss.
| Pass | Tool | Catches |
|---|---|---|
| Authoring | Biome rule noSvgWithoutTitle | Inline svg with no text alternative |
| Automated | axe-core rule svg-img-alt (axe-core 4.13) | role=”img” with no usable name |
| Manual | NVDA, JAWS, VoiceOver, TalkBack | Wrong or missing announcement of name, role and description |
Biome’s rule accepts role=”img” with aria-label or aria-labelledby, aria-hidden=”true” and role=”presentation”, so it nudges without forcing one pattern.
The axe-core rule svg-img-alt is rated serious and maps to WCAG 1.1.1 (Deque University). It fails a title nested one level too deep and a whitespace-only title, and it also fails an empty first title among several.
For screen readers, record the announced name, role and description for each browser and screen reader pair. Stay on the pairings each screen reader’s maker recommends, since Smashing Magazine’s tests warn that results elsewhere may be less accurate.
Automation checks that a name exists, and it cannot judge whether the name is right. W3C keeps “image accessible name is descriptive” as a separate test rule from “has non-empty accessible name” for that reason.
Add the three passes to your web accessibility checklist so SVG gets its own line and does not hide inside the image items.
Where Accessible SVG Patterns Break
Most failures come from the build pipeline and from copy-pasted markup, and none of them show in a quick visual check. That’s why they ship.
Optimizers that strip the title
SVGO’s v4 migration guide drops removeTitle from the default preset for accessibility reasons.
Pipelines still on v3, or any config that lists removeTitle, keep deleting names. An aria-labelledby that points at a removed title resolves to nothing.
Docusaurus and SVGR had already switched off removeTitle and removeViewBox by default, according to the SVGO v4 release notes. SVGO’s plugin page limits removal to purely aesthetic graphics, or to cases where the name is supplied elsewhere, such as an aria-label in the HTML.
The wider trade-offs of shrinking files sit in this overview of SVG optimization. For naming, the rule is short. Run the lint pass after the build, not before.
Ids that collide
Paste the same inline icon five times with one title id and aria-labelledby resolves to the first match in the document, so every copy announces the first copy’s name. Two components that both use a generic id such as “title” collide the same way.
Generate ids per instance, or drop the title and use aria-label when the icon repeats with the same meaning.
Sprites and use references
The SVG-AAM draft lists changed handling of use-element shadow content among its revisions, so exposure of a title inside a referenced symbol is not settled behavior (as of the September 2026 draft). Deque has also flagged older and mobile browsers that struggle with the use element.
Put the role and name on the svg that references the symbol, or on the control wrapped around it, and keep the symbol itself to shapes.
Names that exist but mislead
A text alternative that leaves out what the colors convey fails 1.1.1 and 1.4.1 (failure F13). Stale text is the same kind of problem, like a chart that updates while its description does not (failure F20, which fails 1.1.1 and 4.1.2). A long description that doesn’t match the information in the graphic fails 1.1.1 too (failure F67).
Automated rules pass all of these, because each graphic has a non-empty name. Only a person reading the name next to the picture catches them.
Accessible SVG Files FAQ
Are SVG files accessible by default?
No. The W3C ACT rule for SVG names (June 2022) notes that the svg element carries an implicit graphics-document role, yet support for title and desc stays inconsistent across browsers and assistive technology. Its own advice is to remove decorative SVGs from the accessibility tree explicitly.
Should I use graphics-document or graphics-symbol instead of the img role?
Keep img for a single graphic read as one whole. The WAI-ARIA Graphics Module (W3C Recommendation, October 2018) adds graphics-document for structured charts, maps and diagrams and graphics-symbol for atomic icons, and it advises listing img as a fallback, as in role=”graphics-symbol img”.
Does the lang attribute matter for text inside an SVG?
Yes, whenever the text differs from the page language. WCAG 3.1.2 (AA) requires each passage’s language to be programmatically determinable, except for proper names and technical terms.
Accessible names are flat strings, so W3C cites setting lang on the element itself as a workaround, one that may not work in every browser and screen reader pair.
Can the tooltip from an SVG title replace a visible label?
No. MDN notes that browsers may show the title as a tooltip when the SVG is hovered, which makes it optional and pointer-only.
Keyboard and touch users need visible text or a labeled control.
Does Inkscape support accessible SVG?
Partly. The Inkscape wiki documents that, as of version 0.91, the Object Properties dialog sets title and desc, and a title in the document metadata becomes the document-level title.
It lists no support for role or aria-labelledby, so add those in the XML editor or in code, and check your current release.
Why does a screen reader announce my SVG as a diagram or graphic?
Without an explicit role, browsers map an svg to their own graphic types. TPGi’s 2013 testing found Internet Explorer exposed a graphic and Firefox a diagram, while adding role=”img” produced graphic or image in every browser tested.
Treat those versions as history and set the role yourself.
Which SVG Checks Are Worth Automating First
Accessible SVG files only survive every export and optimization if something checks them automatically. A lint rule on the source files and an axe-core run on rendered pages cover most of it, and a guard on the optimizer config covers the rest.
Per-file checks run first because they fail fastest. The config guard comes second because one setting, such as SVGO’s removeTitle plugin, can undo every name at once.
The cost is friction. A strict lint rule flags decorative icons too, so each one needs an explicit aria-hidden decision.
W3C’s ACT rule keeps its advice to hide decorative SVG explicitly until browsers support SVG-AAM consistently, and that specification remains a working draft (verified 11 October 2026).
Icon buttons are the natural next step, since the same naming checks apply across accessible UI components.
- What is Backend in Web Development? - September 13, 2026
- What is Frontend Development? - September 11, 2026
- How to Make a Button in Figma: Design Best Practices - September 10, 2026


