Inline SVG in React — Component vs Data URI, When to Use Each
React gives you two ways to use SVG: as a JSX component or as a data URI in an <img> tag. Both work — understanding their tradeoffs keeps your bundle lean and your UI flexible.
The two approaches
1. SVG as a React component
Copy the SVG markup into a .tsx file. Convert attribute names to JSX conventions (stroke-width → strokeWidth), wrap it in a component, and import it anywhere:
// Icon.tsx
import type { SVGProps } from 'react';
export default function Icon(props: SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth={2}
{...props}
>
<path d="M12 2L2 7l10 5 10-5-10-5Z" />
<path d="m2 17 10 5 10-5" />
<path d="m2 12 10 5 10-5" />
</svg>
)
}
// Usage
import Icon from './Icon';
<Icon className="text-blue-500 w-6 h-6" />This is what SVG Encoder's React/JSX tab generates — ready-to-paste TypeScript with correct prop types.
2. SVG as a data URI in an <img> tag
Encode the SVG string into a data URI and use it as an image source. No component wrapper, no import path — the SVG data lives entirely in your CSS or JS:
/* CSS file */
.icon-check {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center;
}Or in JSX:
// Usage in React
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"
alt="Checkmark"
/>SVG Encoder handles the encoding — paste your SVG and copy the raw data URI, CSS snippet, or HTML tag.
Tradeoffs at a glance
| Factor | React Component | Data URI <img> |
|---|---|---|
| Bundle size impact | Adds to JS bundle — every imported SVG component increases parse/execute time | Zero JS cost when used in CSS. Minimal JS cost in JSX (just a src string) |
| Styling | Full CSS control via props, className, or style — recolor, resize, animate | Cannot style the SVG internals from CSS. Best for icons with fixed or currentColor fills |
| Interactivity | Can attach event handlers, hover effects, CSS animations to internal elements | None — rendered as a raster equivalent. Use CSS hover on the <img> wrapper only |
| Caching | Inline in JS bundle — cacheable only if the chunk is cached | Embedded in CSS — cached as part of the stylesheet. Can also be a separate HTTP request if externalized |
| Accessibility | Text content inside SVG is accessible. Use <title> and <desc> as with any SVG | Requires alt attribute on the <img> tag. No internal structure exposed to assistive tech |
| JSX conversion effort | Zero — SVG Encoder produces the TSX component | Zero — paste SVG into SVG Encoder, copy the data URI or HTML snippet |
When to use each
Use a React component when:
- You need to recolor the SVG via CSS props or
currentColorinheritance (design system icons) - The SVG has interactive elements — hover states, click targets, animated paths
- The SVG is used a handful of times across your app (import cost is amortized)
- You need to dynamically change SVG attributes (
viewBox, paths, etc.)
Use a data URI when:
- The SVG is purely decorative — background patterns, loading spinners, decorative dividers
- You can express the color with
currentColoror it has a fixed fill - Bundle size is tight and every kilobyte counts (SVG as CSS avoids JS parse cost)
- The SVG appears in CSS (
background-image,mask-image) — data URI is the only option - You want to reference the same SVG from multiple CSS classes without importing a component
A practical example
Say you ship a library of 50 icon components. A typical icon SVG is 300–800 bytes minified. Importing all 50 as React components adds roughly 25–40 KB of JS (parsed and executed on every page load). Using data URIs in CSS for the less-interactive subset (say, 30 of the 50) moves ~20 KB from JS to CSS, which is processed differently by the browser — no parse cost, no execution.
The dev tool SVG Encoder supports both workflows in one interface: copy a TSX component from the React/JSX tab, or grab the data URI / CSS / HTML snippet from the other format tabs. No tab-switching between separate tools.
SSR and RSC considerations
In Next.js App Router, inline SVG components render on the server just like any JSX — they stream as HTML and hydrate on the client. Data URIs in CSS work identically in server and client rendering; the CSS is extracted at build time or served as a separate stylesheet.
If you're using Server Components heavily, data URIs in CSS are a natural fit — they don't require 'use client' directives, while SVG components with interactive behavior must be client components.
Bottom line
The choice isn't binary — most apps use both. Core icons that need color flexibility and interactivity go in as React components. Background patterns, decorative elements, and fixed-color icons go in as data URIs. The trick is knowing which is which, and having a tool that can produce either format from the same source SVG.
SVG Encoder is a free, client-side tool that converts SVG to URL-encoded and Base64 data URIs for CSS and HTML, plus generates ready-to-paste React/JSX TypeScript components. Your SVGs never leave your browser.