mgifford/accessibility-skills/svg
Claude Code and agent skill by mgifford/accessibility-skills
- community
Checking that the SKILL.md file is still in the repository.
Load this skill whenever the project contains SVG graphics — inline SVGs, external SVG files, SVG icons, SVG illustrations, or SVG-based data visualizations. Under no circumstances use SVG without proper accessible titles, descriptions, and ARIA roles where required. Absolutely always add <title> and <desc> to meaningful SVGs and set role="img" with aria-labelledby pointing to those elements. Also apply this skill whenever the project accepts untrusted or user-uploaded SVG content, which requires sanitization before rendering.
Install
npx vskill@latest install mgifford/accessibility-skills/svgSKILL.md
SVG Accessibility Skill
Canonical source:examples/SVG_ACCESSIBILITY_BEST_PRACTICES.mdinmgifford/ACCESSIBILITY.mdThis skill is derived from that file. When in doubt, the example is authoritative.
Apply these rules when creating, optimising, or reviewing SVG graphics. Only load this skill if the project contains SVGs.
Core Mandate
SVG accessibility depends on the graphic's purpose and how it is embedded. A decorative icon, an informative image, an icon inside a button, and an interactive diagram require different patterns. Start by deciding what users need from the graphic, then provide the simplest semantic implementation that delivers the same information or function. The presence of <title>, <desc>, role="img", or aria-label does not by itself make an SVG accessible — test the result in its final context.
SVG is also an active XML format that can contain scripts, event handlers, and external resource references. Untrusted SVG (uploads, pasted markup, AI-generated output) must be sanitized before rendering — see the Security section below.
Severity Scale (this skill)
| Level | Meaning | |
|---|---|---|
| Critical | SVG conveys essential information with no accessible alternative; untrusted SVG rendered without sanitization | |
| Serious | SVG is interactive but unreachable or unlabelled for AT users | |
| Moderate | AT experience degraded but content still partially accessible | |
| Minor | Best-practice gap; marginal impact |
Choose the Pattern by Purpose and Context
| Context | Preferred pattern | |
|---|---|---|
Decorative SVG loaded with <img> | <img src="…" alt=""> | |
Meaningful SVG loaded with <img> | <img src="…" alt="Useful description"> | |
| Decorative inline SVG | <svg aria-hidden="true">…</svg> | |
| Simple meaningful inline SVG | <svg role="img" aria-labelledby="…"><title>…</title></svg> | |
| Icon inside a named button or link | Name the HTML control and hide the SVG | |
| Complex graphic | Short name plus visible summary, data, or detailed description | |
| Reused sprite icon | Label or hide each outer <svg> instance, not the shared symbol | |
| Interactive graphic | Prefer native HTML controls; provide an equivalent structured alternative |
Use native HTML semantics before ARIA. Do not add role="img" to an <img> merely because its source is an SVG file — that's redundant.
Critical: Decorative SVGs Must Be Hidden Completely from AT
aria-hidden="true" removes the SVG and its descendants from the accessibility tree — do not place focusable or interactive content inside an element hidden this way. focusable="false" addresses legacy IE/older Edge behavior; it can remain for projects still supporting those browsers but isn't a universal modern requirement. Do not add <title>/<desc> to an intentionally-hidden SVG. Never use `role="presentation"` as a substitute for aria-hidden="true" — it does not reliably suppress announcement across browser/screen-reader combinations.
When is an SVG decorative? If the same meaning is conveyed by adjacent visible text, or the image is purely ornamental, it's decorative. If removing it would leave a user without needed information, it's meaningful.
External SVG Used with <img>
Follows the same text-alternative rules as other image formats.
role="img" is redundant on <img>; aria-label unnecessary when alt can provide the name. Internal SVG `<title>`/`<desc>` does not replace HTML `alt` when loaded through <img> — the HTML alt is what's read.
Serious: Simple Meaningful Inline SVG
The <title> must be a direct child of <svg> with a unique ID, referenced via aria-labelledby. A plain aria-label is a reasonable alternative when managing a unique title ID adds needless complexity:
Do not use both patterns without a specific tested reason — ARIA labelling attributes take priority over <title> in the accessible-name calculation (aria-labelledby > aria-label > direct child <title>). Note: some browsers show <title> as a pointer tooltip — that is not a substitute for visible text or a real accessible tooltip; it may not be discoverable by keyboard, touch, or speech-input users.
Serious: Icons Inside Buttons and Links
The HTML control should own the accessible name — hide the SVG icon.
Do not give both the button and its hidden icon separate versions of the same name — that produces duplicate or inconsistent announcements. Prefer a visible label when the action may not be obvious — a familiar-looking icon can mean different things across products.
For an external SVG asset loaded via <img> inside an already-labelled button (e.g., a theme selector), use alt="" since the button supplies the name — note that an external <img>-loaded SVG does not inherit currentColor from the surrounding button; validate the asset's own colors on every background it appears on, or inline the paths if it must follow a manual theme.
Serious: Accessible Names and Descriptions — Correct ARIA Relationship
SVG accessible-name priority: aria-labelledby > aria-label > direct child <title> > other fallbacks. Descriptions: aria-describedby > direct child <desc>.
Keep IDs unique in the whole HTML document — a repeated component with fixed SVG IDs can cause one instance to be labelled by another. Do not put both title and description IDs in `aria-labelledby` — that concatenates both strings into the accessible name; use aria-labelledby for the name and aria-describedby for the description separately. Do not bury essential information in `<desc>` — support for navigating long SVG descriptions varies across AT; put essential details in visible HTML instead.
Moderate: Complex Graphics, Diagrams, and Charts
A complex SVG needs more than one long accessible name: a concise name, a visible summary of the purpose/conclusion, complete data in structured HTML when needed, and keyboard-operable controls if interactive.
Do not duplicate a detailed table into aria-label/<title>/<desc> — long image-name strings are hard to navigate. The ARIA Graphics Module defines structured roles (graphics-document, graphics-object, graphics-symbol) but support must be tested with actual AT combinations; these don't remove the need for an equivalent text presentation. See skills/charts-graphs/SKILL.md for chart-specific requirements.
Reused Icons and SVG Sprites
Names inside a shared symbol are rarely appropriate for every instance — "Arrow" could mean Next, Previous, Expand, or Collapse depending on context. Name the control or the outer rendered instance, not the shared symbol. An external <use> target must reference a real distinct element (usually a <symbol> with an ID) — do not create recursive self-references.
Moderate: Colour, Contrast, and Themes
currentColor is useful, not mandatory — multi-colour graphics may need several semantic tokens; validate every meaningful pairing in every theme. Do not rely on colour alone — add text labels, patterns, line styles, or shapes for statuses/series/selected states. Text inside SVG is subject to text contrast requirements; required graphical information generally needs 3:1; decorative details don't need 3:1 merely for appearing in a meaningful graphic.
Do not set both fill and stroke on every path indiscriminately — it can turn line artwork into solid shapes. Avoid forced-color-adjust: none unless essential and tested against multiple system palettes.
Text Inside SVG
Keep essential labels visible and legible; meet text contrast requirements. Do not convert essential labels to paths merely to preserve a typeface, and do not use font-size="0", off-canvas positioning, or transparent SVG text as a substitute for a real text alternative. Provide important explanations in HTML. Test resizing/zoom — SVG labels can overlap or clip even when the outer SVG scales. <foreignObject> can embed HTML in SVG but adds rendering/fallback complexity — use ordinary HTML outside the SVG when it can provide the same result.
Critical: Interactive SVG
Prefer native HTML buttons, links, and disclosures placed near the graphic over interaction inside the SVG itself:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/svg/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/mgifford/accessibility-skills/svg)