A practical React field guide
Accessible SVG icons in React
Start with one question: does this icon add information, or is its meaning already provided by nearby text? That answer determines whether the SVG needs a name or should be hidden from assistive technology.
These patterns cover inline SVG components and SVG files rendered with <img>. They help with common markup mistakes; they do not certify a page against WCAG. You can paste a standalone SVG into the free SVG Ready checker to inspect labels, ID references, and other first-pass issues.
1. An icon beside visible button text
When text already names the action, hide the decorative icon. The button's visible text supplies its accessible name, so announcing the icon as well would repeat information.
function SaveButton() {
return (
<button type="button">
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
<path d="…" />
</svg>
Save changes
</button>
);
}
2. An icon-only button
Name the button itself. This keeps the action clear to everyone and avoids making an icon carry both the control's role and its purpose.
function CloseButton({ onClose }) {
return (
<button type="button" aria-label="Close dialog" onClick={onClose}>
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
<path d="…" />
</svg>
</button>
);
}
3. A standalone meaningful icon
If the graphic itself conveys information, expose it as an image and give it a concise name. A title linked by aria-labelledby works, but the referenced ID must be unique each time the component appears.
function StatusIcon() {
return (
<svg role="img" aria-label="Payment received" viewBox="0 0 24 24">
<path d="…" />
</svg>
);
}
For an external SVG file, put the text alternative on the HTML image element:
<img src="payment-received.svg" alt="Payment received" />
4. Repeated icons and duplicate IDs
SVG IDs are document-wide identifiers. If a component repeats an ID such as title, aria-labelledby can point to the wrong title. Create a unique ID with React's useId, or use a direct aria-label when a short fixed name is enough.
import { useId } from "react";
function NamedGraphic({ label }) {
const titleId = useId();
return (
<svg role="img" aria-labelledby={titleId} viewBox="0 0 24 24">
<title id={titleId}>{label}</title>
<path d="…" />
</svg>
);
}
5. A quick review before shipping
- Decide whether the icon is informative or decorative in this specific place.
- Put the name on the button or link when the icon is inside a control.
- Make every
aria-labelledbyreference resolve to an existing, unique ID. - Check the icon's contrast and meaning in the real layout; a markup checker cannot judge those by itself.
- Try the control with a keyboard and a screen reader when it carries important information.
Check an SVG free in your browser
If you need a second look at one shareable SVG, request a first-pass review for $5 in USDC on Base. After paying, email the SVG and transaction hash. I will send concise findings within one business day. Do not send private code; this is not a sanitizer or a compliance audit.
Pay $5 USDC on BaseEmail the review request
Further reading
- W3C WAI: Tips for images — guidance for SVG titles and text alternatives.
- W3C WAI: SVG accessible name rule — examples of named SVG graphics.
- React: useId — generate IDs for accessibility relationships.