DevToolBoxGRATIS
Blog

SVG to JSX: Convert SVG for React Components (Complete Guide)

11 min readoleh DevToolBox

TL;DR

SVG files cannot be dropped directly into React because JSX requires camelCase attributes, object-style inline styles, and self-closing tags. You need to convert class to className, kebab-case attributes like stroke-width to strokeWidth, and style strings to JavaScript objects. Use our free SVG to JSX converter to automate the entire process instantly.

Key Takeaways

  • JSX requires camelCase attribute names: fill-rule becomes fillRule, stroke-linecap becomes strokeLinecap
  • class must be renamed to className and for to htmlFor
  • Inline style attributes change from strings to JavaScript objects with camelCase property names
  • All SVG tags must be explicitly self-closed in JSX (e.g., <path /> not <path>)
  • Optimize SVG with SVGO before conversion to remove editor bloat and reduce file size by 30-60%
  • Wrap converted SVG in React components with props for dynamic color, size, and accessibility

Why SVG Needs Conversion for React

SVG (Scalable Vector Graphics) is the standard format for icons, logos, and illustrations on the modern web. Every design tool from Figma to Illustrator exports SVG, and developers use it everywhere because it scales perfectly to any screen resolution without quality loss.

However, you cannot simply copy raw SVG markup into a React component and expect it to work. React uses JSX, a syntax extension for JavaScript that looks like HTML but follows different rules. JSX compiles to React.createElement() calls, and because it lives inside JavaScript, it must respect JavaScript naming conventions and reserved words.

The result: attributes like class, fill-rule, and stroke-width that are perfectly valid in SVG will trigger React warnings or outright break your component. Inline style strings will throw compilation errors. Unclosed tags like <path> without a self-closing slash will fail to parse. Converting SVG to JSX solves all these issues and makes your graphics first-class React citizens.

Key Differences Between SVG and JSX Syntax

Understanding the specific differences between raw SVG attributes and their JSX equivalents is essential before you start converting. Here is the complete reference table:

SVG / HTML AttributeJSX EquivalentReason
classclassNameclass is a reserved JavaScript keyword
forhtmlForfor is a reserved JavaScript keyword
fill-rulefillRuleJSX uses camelCase for multi-word attributes
clip-ruleclipRulecamelCase convention
clip-pathclipPathcamelCase convention
stroke-widthstrokeWidthcamelCase convention
stroke-linecapstrokeLinecapcamelCase convention
stroke-linejoinstrokeLinejoincamelCase convention
stroke-dasharraystrokeDasharraycamelCase convention
stroke-dashoffsetstrokeDashoffsetcamelCase convention
font-sizefontSizecamelCase convention
text-anchortextAnchorcamelCase convention
xlink:hrefxlinkHrefNamespaced attributes use camelCase (or remove entirely for modern SVG)
style="fill: red"style={{ fill: "red" }}JSX style must be a JavaScript object, not a string

Missing even one of these conversions will produce a React console warning and may cause the SVG to render incorrectly. For a full HTML-to-JSX attribute reference, see our HTML to JSX migration guide.

Manual SVG to JSX Conversion: Step by Step

For a quick one-off conversion, you can manually transform SVG to JSX in six steps. Here is the process with a before-and-after example.

Step 1: Start with your raw SVG markup (exported from Figma, Illustrator, or downloaded from an icon library):

<!-- Raw SVG from design tool -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon-alert"
     width="24" height="24" viewBox="0 0 24 24"
     fill="none" stroke="currentColor" stroke-width="2"
     stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"></circle>
  <line x1="12" y1="8" x2="12" y2="12"></line>
  <line x1="12" y1="16" x2="12.01" y2="16"></line>
</svg>

Step 2-5: Apply all the required transformations:

  • Remove xmlns (not needed for inline SVG in HTML5)
  • Replace class with className
  • Convert stroke-width to strokeWidth
  • Convert stroke-linecap to strokeLinecap
  • Convert stroke-linejoin to strokeLinejoin
  • Self-close all tags: <circle ... /> instead of <circle ...></circle>

Step 6: The converted JSX result:

<svg className="icon-alert"
     width="24" height="24" viewBox="0 0 24 24"
     fill="none" stroke="currentColor" strokeWidth="2"
     strokeLinecap="round" strokeLinejoin="round">
  <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>

The converted output is valid JSX that React can render without any warnings. For SVG files with dozens of paths and attributes, manual conversion is tedious and error-prone, which is why automated tools exist.

Using an Automated SVG to JSX Converter

Manual conversion works for small icons, but real-world SVGs from design tools often contain hundreds of attributes, nested groups, gradients, and metadata. An automated converter handles everything in a single pass:

  • Renames all HTML/SVG attributes to their camelCase JSX equivalents
  • Converts inline style strings to JavaScript style objects
  • Self-closes all void elements (path, circle, rect, line, polyline)
  • Removes unnecessary xmlns declarations and editor metadata
  • Preserves the viewBox and essential SVG structure

Our free SVG to JSX converter does all of this instantly. Paste your raw SVG, get production-ready JSX. No sign-up, no installation, no external dependencies. If your SVG also contains HTML elements, our HTML to JSX converter handles the full spectrum of HTML-to-JSX transformations.

SVG as React Components: Inline vs File Import

Once your SVG is converted to valid JSX, you have two approaches for using it in React: inline components and file imports. Each has distinct trade-offs.

Approach 1: Inline SVG Components

Define the SVG markup directly inside a React component function. This is the most common pattern for icons and small graphics:

// components/icons/AlertIcon.tsx
interface AlertIconProps extends React.SVGProps<SVGSVGElement> {
  size?: number;
}

export function AlertIcon({ size = 24, ...props }: AlertIconProps) {
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      {...props}
    >
      <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: Full CSS and JS control, dynamic props, tree-shakeable, no extra HTTP requests, works with SSR.
Cons: Increases JavaScript bundle size, cannot be cached separately from your JS bundle.
Best for: Icons, logos, and small illustrations under 5KB each.

Approach 2: SVG File Imports (with build tool support)

Tools like SVGR (used by Create React App, Vite, and Next.js) let you import .svg files directly as React components:

// With SVGR configured in your bundler
import { ReactComponent as AlertIcon } from './alert.svg';
// or with Next.js @svgr/webpack:
import AlertIcon from './alert.svg';

function App() {
  return <AlertIcon width={32} height={32} className="text-red-500" />;
}

Pros: Keeps SVG files separate and editable, build tool handles conversion automatically, cleaner source code.
Cons: Requires build configuration, still inlines into JS bundle at build time.

Optimizing SVG Before Conversion with SVGO

SVG files exported from design tools are almost always larger than they need to be. Figma, Sketch, and Illustrator embed editor metadata, comments, empty groups, default attribute values, and unnecessary precision in coordinates. SVGO (SVG Optimizer) is the standard tool for cleaning this up.

Running SVGO before converting to JSX typically reduces file size by 30-60%. Here is what SVGO removes:

  • xmlns when not needed for inline SVG
  • XML declarations and DOCTYPE
  • Editor metadata (data-name, sketch:type, inkscape:*)
  • HTML comments
  • Empty <defs> and <g> groups
  • Default attribute values that browsers already apply
  • Unnecessary coordinate precision (e.g., 12.000000 to 12)
  • Redundant fill and stroke attributes that inherit from parent

You can use SVGO via the CLI (npx svgo input.svg -o output.svg) or use our online SVG Optimizer tool which runs SVGO in the browser with no installation needed. Always optimize first, then convert to JSX for the cleanest result.

Dynamic SVG with Props: Color, Size, and Animation

One of the biggest advantages of SVG-as-React-components over <img> tags is the ability to control SVG properties dynamically through React props. Here is a flexible icon component pattern:

interface IconProps extends React.SVGProps<SVGSVGElement> {
  size?: number;
  color?: string;
  title?: string;
}

function StarIcon({
  size = 24,
  color = "currentColor",
  title,
  ...props
}: IconProps) {
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 24 24"
      fill={color}
      role={title ? "img" : undefined}
      aria-label={title}
      aria-hidden={title ? undefined : true}
      {...props}
    >
      {title && <title>{title}</title>}
      <path d="M12 2l3.09 6.26L22 9.27l-5 4.87
               1.18 6.88L12 17.77l-6.18 3.25L7 14.14
               2 9.27l6.91-1.01L12 2z" />
    </svg>
  );
}

Usage examples with dynamic props:

{/* Default: 24px, inherits text color */}
<StarIcon />

{/* Custom size and explicit color */}
<StarIcon size={48} color="#f59e0b" />

{/* With accessibility label for screen readers */}
<StarIcon size={20} color="#ef4444" title="Favorite" />

{/* With CSS class for Tailwind styling */}
<StarIcon className="w-6 h-6 text-yellow-400 hover:text-yellow-500" />

{/* With click handler */}
<StarIcon onClick={() => toggleFavorite()} style={{ cursor: 'pointer' }} />

The currentColor technique is especially powerful: setting fill="currentColor" or stroke="currentColor" makes the SVG inherit the CSS color property from its parent element, enabling automatic theme switching (light/dark mode) without any prop changes.

SVG Accessibility: ARIA Labels and Roles

SVG icons are invisible to screen readers by default. Without proper ARIA attributes, assistive technology will either skip the icon entirely or read out meaningless path data. Here are the three scenarios you need to handle:

1. Decorative Icons (alongside text)

When the icon appears next to a text label that already conveys the meaning, the icon is purely decorative and should be hidden:

<button>
  <TrashIcon aria-hidden="true" focusable="false" />
  <span>Delete</span>
</button>

2. Meaningful Icons (standalone, no text)

When the icon is the only content and conveys meaning, it needs a label:

<StarIcon role="img" aria-label="Rated 4 out of 5 stars" />

3. Interactive Icons (inside buttons or links)

When the icon is inside an interactive element without visible text, label the interactive element itself:

<button aria-label="Close dialog">
  <CloseIcon aria-hidden="true" focusable="false" />
</button>

Additionally, include a <title> element as the first child inside the <svg> tag. This provides a tooltip on hover in most browsers and serves as a fallback description for older assistive technology. Ensure that SVG icon colors meet the WCAG 2.1 minimum contrast ratio of 3:1 against their background.

Common Pitfalls and Fixes

Even experienced React developers run into these SVG conversion issues. Here is a quick reference for the most common problems and their solutions:

Pitfall 1: Forgetting to convert class to className

React will silently ignore the class attribute and your styles will not apply. Always search for class= and replace with className=.

Pitfall 2: Style attribute as a string

<!-- WRONG: will throw a compilation error -->
<svg style="fill: red; stroke-width: 2px">

<!-- CORRECT: JSX style object with camelCase -->
<svg style={{ fill: 'red', strokeWidth: '2px' }}>

Pitfall 3: Unclosed SVG elements

Tags like <path>, <circle>, <rect>, and <line> must be self-closed in JSX with a trailing slash: <path d="..." />.

Pitfall 4: Namespace attributes

SVG attributes with colons like xlink:href and xml:space are not valid JSX. Convert xlink:href to xlinkHref (or replace with plain href for modern SVG) and remove xml:space entirely.

Pitfall 5: Duplicate id attributes

Design tools generate auto-incremented IDs (id="Layer_1", id="SVGID_1_"). If you use the same SVG component multiple times, these duplicate IDs cause rendering glitches with gradients, clip paths, and filters. Either remove IDs or make them unique per instance with a prefix prop.

Pitfall 6: viewBox casing

The viewBox attribute is case-sensitive. Writing viewbox (lowercase b) will silently break SVG scaling. Always use viewBox with a capital B.

Frequently Asked Questions

What is the difference between SVG and JSX?

SVG uses standard HTML/XML attributes (class, fill-rule, stroke-width) while JSX requires JavaScript-compatible equivalents (className, fillRule, strokeWidth). JSX also requires all tags to be explicitly closed, style attributes to be objects instead of strings, and does not support XML namespaces like xmlns or xlink:href in the standard way.

How do I convert SVG to a React component?

Convert SVG to a React component by: (1) replacing class with className, (2) converting kebab-case attributes to camelCase, (3) converting inline style strings to JavaScript objects, (4) removing xmlns, (5) self-closing all void tags, and (6) wrapping in a function component. Use our SVG to JSX converter for instant automated results.

Do I need to remove xmlns from SVG in React?

When using inline SVG inside JSX, the xmlns attribute is not required because the browser already knows the SVG namespace from the HTML5 parser. Removing it slightly reduces markup size. However, keeping xmlns will not cause errors in React, so it is a minor optimization rather than a requirement.

Should I use inline SVG or img tags for SVG in React?

Use inline SVG components for icons and small graphics (under 5KB) that need dynamic styling, animation, or prop-based color changes. Use <img> tags for large, complex SVGs like maps or detailed illustrations that benefit from browser caching and do not need JavaScript interaction. For more details, see our SVG to React component guide.

How do I make SVG accessible in React?

For decorative SVGs, add aria-hidden="true" and focusable="false". For meaningful SVGs that convey information, add role="img" and aria-label with a descriptive label. Include a <title> element inside the SVG as a fallback. Ensure icon color contrast meets the WCAG 2.1 minimum of 3:1 against the background.

Related Developer Tools and Guides

𝕏 Twitterin LinkedIn
Apakah ini membantu?

Tetap Update

Dapatkan tips dev mingguan dan tool baru.

Tanpa spam. Berhenti kapan saja.

Coba Alat Terkait

SVGSVG to JSX/ReactJSXHTML to JSX💎SVG Optimizer

Artikel Terkait

HTML ke JSX: Semua yang Anda Butuhkan untuk Migrasi ke React

Panduan lengkap mengonversi HTML ke JSX untuk React. Mencakup className, objek style, tag self-closing, event handler, dan kesalahan umum.

SVG di React: Dari SVG Mentah ke Komponen yang Dioptimalkan

Pelajari cara mengubah SVG mentah menjadi komponen React yang efisien. Optimasi SVGO, aksesibilitas, animasi, dan props TypeScript.

SVG ke Komponen React: Panduan Konversi Lengkap

Pelajari cara mengonversi SVG ke komponen React dengan SVGR. Konversi atribut JSX, aksesibilitas, performa, TypeScript, dan Next.js.