How to Use SVG Icons in React (2025 Guide)
Learn the four main ways to use SVG icons in React apps — inline SVG, React icon components, SVG sprites, and icon fonts — with real code examples and performance tips.
Icons are everywhere in web apps — navigation bars, buttons, empty states, form fields. But the "right" way to use SVG icons in React is not obvious. There are four main approaches, each with real trade-offs.
This guide walks through all of them so you can pick the one that fits your project.
Option 1 — Inline SVG (copy-paste)
The simplest approach: copy an SVG file's markup and paste it directly into your JSX.
export function AlertIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<circle cx="12" cy="12" r="10" />
<line x1="12" y1="8" x2="12" y2="12" />
<line x1="12" y1="16" x2="12.01" y2="16" />
</svg>
);
}
Pros: Zero dependencies. Full control over every attribute. Works with any styling approach.
Cons: Does not scale. Hundreds of icons means hundreds of hand-maintained components. Updating a design system change requires touching every file.
Use it when: You need one or two custom icons that won't change.
Option 2 — React icon component library
A library like krz-icons ships every icon as a ready-made React component. You install the package once and import the icons you need.
import { Bell, Home, Search } from "krz-icons";
export function Navbar() {
return (
<nav>
<Home size={20} />
<Search size={20} />
<Bell size={20} />
</nav>
);
}
All three props — size, color, and strokeWidth — accept any value and fall back to sane defaults (24, "currentColor", and 1). Any other prop is forwarded to the underlying <svg> element.
Pros: Fast to use. Fully typed (autocomplete in VS Code). Tree-shakeable — only the icons you import end up in your bundle.
Cons: You depend on the library's design decisions. Good libraries like krz-icons are consistent and large (20 000+ icons), but you need to trust the grid and stroke choices.
Use it when: You want a large, consistent set of icons with minimal setup — the common case for production apps.
Option 3 — SVG sprites
A sprite is a single SVG file that holds many icon definitions as <symbol> elements. You reference them with <use> and an href.
// sprite.svg (generated at build time)
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="home" viewBox="0 0 24 24">...</symbol>
<symbol id="search" viewBox="0 0 24 24">...</symbol>
</svg>
// Usage
<svg width="20" height="20">
<use href="/sprite.svg#home" />
</svg>
Pros: One network request for all icons. Browser caches the file. Works in plain HTML without React.
Cons: Harder to control individual icon styles with CSS. Requires a build step to generate the sprite file. Cross-origin <use> references can be blocked by browsers.
Use it when: You have a stable, small icon set and want one cached asset with no JavaScript.
Option 4 — Icon fonts
Icon fonts (like Font Awesome 4) encode each icon as a Unicode character in a custom font file.
<!-- HTML -->
<i class="fa fa-home"></i>
Pros: CSS-only. Every font technique (size, color, shadow) works. Easy to use in non-React apps.
Cons: Bad accessibility by default. Large font files even if you use two icons. Anti-aliasing issues on some screens. Font loading causes FOIT (flash of invisible text).
Use it when: You are in a non-React codebase that already uses icon fonts and changing would be disruptive.
Performance comparison
| Method | Bundle impact | Render cost | DX |
|---|---|---|---|
| Inline SVG | Low (custom only) | Low | Poor at scale |
| React components | Low (tree-shaken) | Low | Excellent |
| SVG sprite | Zero JS | Very low | Medium |
| Icon font | Medium (font file) | Low | Easy but fragile |
Making icons accessible
SVG icons that are purely decorative should be hidden from screen readers. Pass aria-hidden="true" (krz-icons does this automatically) so assistive technology skips them.
When an icon carries meaning — for example a standalone button — pass a title prop or an aria-label on the surrounding button.
<button aria-label="Search">
<Search size={20} />
</button>
Conclusion
For most React projects, a tree-shakeable component library is the best starting point. You get type safety, a consistent visual language, and instant autocomplete. If you need something beyond a library's catalog, inline SVG is always there as a fallback.
Browse 20 000+ free icons or install krz-icons to get started.