Skip to content

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-widthstrokeWidth), 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

FactorReact ComponentData URI <img>
Bundle size impactAdds to JS bundle — every imported SVG component increases parse/execute timeZero JS cost when used in CSS. Minimal JS cost in JSX (just a src string)
StylingFull CSS control via props, className, or style — recolor, resize, animateCannot style the SVG internals from CSS. Best for icons with fixed or currentColor fills
InteractivityCan attach event handlers, hover effects, CSS animations to internal elementsNone — rendered as a raster equivalent. Use CSS hover on the <img> wrapper only
CachingInline in JS bundle — cacheable only if the chunk is cachedEmbedded in CSS — cached as part of the stylesheet. Can also be a separate HTTP request if externalized
AccessibilityText content inside SVG is accessible. Use <title> and <desc> as with any SVGRequires alt attribute on the <img> tag. No internal structure exposed to assistive tech
JSX conversion effortZero — SVG Encoder produces the TSX componentZero — 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 currentColor inheritance (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 currentColor or 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.