krz-icons logo
Blog

Accessible SVG Icons in React: A Practical Guide

How to make SVG icons accessible in React apps — hiding decorative icons from screen readers, labelling interactive icons, and testing with NVDA, VoiceOver, and axe.


Icons seem simple, but they are a surprisingly common source of accessibility issues. An icon inside a button with no visible label, an SVG that reads out its path data, a tooltip that never reaches keyboard users — any of these can break an otherwise solid experience.

This guide covers every pattern you will encounter when using SVG icons in a React app.

Rule 1: Decorative icons must be hidden

An icon that sits next to visible text carries no additional information. A screen reader that reads both the icon's internal content and the label text creates noise.

// ✅ Hidden from screen readers — icon is decorative
<button>
  <Home size={16} aria-hidden="true" />
  Dashboard
</button>

krz-icons sets aria-hidden="true" on every icon by default, so this works out of the box. You do not need to add it yourself unless you override the prop.

Rule 2: Icon-only interactive elements need a label

A button that contains only an icon has no accessible name unless you provide one. Use aria-label on the button — not on the icon.

// ✅ Button has an accessible name
<button aria-label="Close dialog">
  <X size={18} />
</button>

// ❌ The icon's aria-hidden removes it from the tree,
//    leaving the button with no accessible name
<button>
  <X size={18} />
</button>

Rule 3: Standalone informational icons need a title

Occasionally an icon carries meaning without adjacent text — a status dot, a severity badge, a checkmark in a table cell. Use the title prop (krz-icons), which adds a <title> element inside the SVG and sets role="img".

// ✅ Reads "Verified" to screen readers
<CheckCircle size={20} title="Verified" />

This generates:

<svg role="img" aria-hidden={undefined} ...>
  <title>Verified</title>
  <!-- paths -->
</svg>

Rule 4: Tooltips must be keyboard-accessible

CSS-only :hover tooltips are invisible to keyboard and touch users. If you add a tooltip to an icon button, make sure it also appears on :focus-visible.

// Tailwind example — shows on hover AND focus
<div className="group relative">
  <button aria-label="Settings" className="focus-visible:ring-2 ...">
    <Settings size={18} />
  </button>
  <div
    role="tooltip"
    className="invisible group-hover:visible group-focus-within:visible ..."
  >
    Settings
  </div>
</div>

Rule 5: Icon color contrast

If an icon communicates meaning (not just decoration), its stroke color must have at least a 3:1 contrast ratio against the background (WCAG 1.4.11 — Non-text contrast). Run icons through a contrast checker if you use subtle grey tones.

Rule 6: Do not rely on color alone

Status icons (error, warning, success) must not use color as the only differentiator. Pair the color with a shape — a different icon per status — so colorblind users can tell them apart.

// ✅ Shape AND color differ
{status === "error"   && <AlertCircle color="red"   title="Error"   />}
{status === "warning" && <AlertTriangle color="amber" title="Warning" />}
{status === "success" && <CheckCircle  color="green" title="Success" />}

// ❌ Only the color changes — shape is the same
{status === "error"   && <Circle color="red"   />}
{status === "warning" && <Circle color="amber" />}
{status === "success" && <Circle color="green" />}

Testing icons for accessibility

  • axe DevTools — browser extension that catches missing labels on icon buttons automatically.
  • VoiceOver (macOS/iOS) — press Cmd + F5, then Tab through the page. Icon buttons without a label will read the button's element type with no name.
  • NVDA (Windows) — free screen reader, Tab through the page to hear how buttons are announced.
  • Keyboard navigation test — unplug your mouse and Tab through the page. Every interactive icon must be reachable and usable.

Summary checklist

  • Decorative icons: aria-hidden="true" (krz-icons default).
  • Icon-only buttons: aria-label on the <button>.
  • Standalone informational icons: title prop.
  • Tooltips: visible on focus as well as hover.
  • Status icons: different shapes, not just different colors.

Find the right icon for every status →


Looking for icons?

Browse 20 000+ free, MIT-licensed SVG and React icons.