SVG to JSX Converter
Convert SVG to a React JSX component instantly in your browser. Handles camelCase attributes, className, optional TypeScript, forwardRef, and memo wrapping. Free, no signup.
- Runs in your browser
- Your data never leaves your browser
- Free · No Sign-Up
Scan with WeChat to share this tool
Examples, details and FAQ Worked examples, how it compares with other tools, and answers to common questions.
Attribute Conversion Rules
| SVG | JSX |
|---|---|
stroke-width | strokeWidth |
stroke-linecap | strokeLinecap |
fill-rule | fillRule |
clip-path | clipPath |
class | className |
font-size | fontSize |
text-anchor | textAnchor |
xmlns="..." | (removed) |
Output Modes
- Default: Plain function component with no TypeScript annotation.
- TypeScript: Adds
React.FC<React.SVGProps<SVGSVGElement>>type so props likeclassName,style, andonClickwork without extra declarations. - forwardRef: Wraps the component in
React.forwardRef, exposing the SVG element ref to the parent. - memo: Wraps the final export in
React.memoto skip unnecessary re-renders.
Common Use Cases
- Converting Figma or Illustrator SVG exports into React icon components
- Migrating an SVG icon library to a JSX-based design system
- Making SVG icons accept
className,style, and other React props - Building accessible icon components that accept an
aria-labelvia spread props
Example
A 24 × 24 plus icon, component name PlusIcon, all options off:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="#000" stroke-width="2" stroke-linecap="round" d="M12 5v14M5 12h14"/></svg>
Output:
import React from 'react';
function PlusIcon(props) {
return (
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" {...props}><path stroke="#000" strokeWidth="2" strokeLinecap="round" d="M12 5v14M5 12h14" /></svg>
);
}
export default PlusIcon;
xmlns is gone, stroke-width and stroke-linecap are camelCase, and the markup is copied as written otherwise. {...props} comes after the root’s own attributes, the same place as svgr’s default (expandProps: 'end'), so props you pass win: <PlusIcon width={48} fill="red" /> renders 48 px and red, and height stays 24. Values stay strings (strokeWidth="2"); React accepts both strings and numbers here. With TypeScript, forwardRef and memo all on, the same icon becomes const PlusIcon = forwardRef<SVGSVGElement, React.SVGProps<SVGSVGElement>>(function PlusIcon(props, ref) { ... }) with ref={ref} {...props} after the <svg>’s own attributes and export default memo(PlusIcon);. In React 19 forwardRef is no longer necessary: a function component can take ref as a prop.
An Illustrator export with Internal CSS, an inline style and xlink:href, component name Icon:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><!-- Generator: Adobe Illustrator --><defs><style>.cls-1{fill:#e11d48;}</style></defs><path id="a" class="cls-1" style="stroke:#000;stroke-width:2" d="M12 5v14"/><use xlink:href="#a"/></svg>
Output:
import React from 'react';
function Icon(props) {
return (
<svg viewBox="0 0 24 24" {...props}>{/* Generator: Adobe Illustrator */}<defs><style>{".cls-1{fill:#e11d48;}"}</style></defs><path id="a" className="cls-1" style={{ "stroke": "#000", "strokeWidth": "2" }} d="M12 5v14" /><use xlinkHref="#a" /></svg>
);
}
export default Icon;
The comment becomes {/* ... */}, which React does not render. The CSS inside <style> becomes one JavaScript string, so its braces are no longer read as JSX; entities in it are decoded and a <![CDATA[ ... ]]> wrapper is removed. The style attribute becomes an object whose values are copied as written, and xlink:href becomes xlinkHref. Compiled with esbuild 0.21.5 and rendered with the React 19.2.0 development build, it gives <svg viewBox="0 0 24 24"><defs><style>.cls-1{fill:#e11d48;}</style></defs><path id="a" class="cls-1" style="stroke:#000;stroke-width:2" d="M12 5v14"></path><use xlink:href="#a"></use></svg> with no console warning.
Before You Paste: Export Settings
- Figma: select the layer, then Export → SVG. Leave “Include ‘id’ attribute” off unless you target elements by ID.
- Illustrator: File → Export → Export As → SVG. Presentation Attributes under Styling gives the shortest component. Internal CSS and Inline Style produce a
<style>block orstyle="..."strings (Adobe: SVG export options); the converter turns them into a CSS string and style objects, as in the example above. A<style>block applies to the whole page, so two icons that both use.cls-1change each other’s colors. - The converter removes the
<?xml ... ?>line and turns comments into JSX comments, so you do not need to delete<!-- Generator: ... -->first.
What You Still Change by Hand
Each row was checked by compiling the output with esbuild 0.21.5 and rendering it with React 19.2.0.
| In the pasted SVG | What the converter outputs | Result in React | Change to |
|---|---|---|---|
style="fill:red !important", a property written twice, or a CSS comment in style | No output: the conversion is refused, Copy is disabled and the status line gives the position in the style | — | Move the rule into the <style> block or a CSS file, or remove !important |
<text>{count}</text> | <text>{count}</text> | Shows the text {count} | Write {count} yourself if you want a variable |
Hard-coded fill or stroke colors | Kept as is | The icon ignores the text color | fill="currentColor" / stroke="currentColor" |
<style> with class names shared by other icons | A CSS string | The rules apply to the whole page | Rename the classes, or export with Presentation Attributes |
Limits
- Pattern matching, not an XML parser. Comments,
<style>blocks and CDATA sections are read first, so a tag written inside<!-- ... -->is not converted. Quoted values may contain>and/. Unclosed tags are not repaired. - Values are copied as written. Only attribute names change:
aria-label="class schedule"staysaria-label="class schedule". The exceptions arestyle, which becomes an object, and text, where{,},<and>are written as{,},<and>so React shows the same characters. - Styles a React object cannot keep are refused.
!important, the same property twice (a CSS fallback), CSS comments, escaped property names and unclosed quotes or brackets in astyleattribute stop the conversion; the output is cleared and Copy is disabled until the input changes. - One component per paste. Only the first
<svg>gets{...props}; paste sprite sheets one icon at a time. - Component name: characters other than letters, digits,
_and$are dropped and the first letter is capitalized (plus-icon→Plusicon). data-*andaria-*attributes keep their hyphens, as React expects.
FAQ
What does an SVG to JSX converter do?
It transforms a raw SVG file into a reusable React component. Key changes include converting hyphenated attributes to camelCase (stroke-width → strokeWidth), renaming class to className, removing the xmlns declaration, and wrapping the SVG markup inside a function component.
Why are SVG attributes renamed in JSX?
JSX is compiled to JavaScript, and hyphenated property names are not valid as JS identifiers. React requires camelCase versions such as strokeWidth, fillRule, and clipPath instead of the SVG/HTML attribute names.
What does the TypeScript option do?
When enabled, the output uses React.FC<React.SVGProps<SVGSVGElement>> as the component type, giving you full TypeScript support including prop autocomplete for SVG attributes.
What is forwardRef used for?
forwardRef lets parent components attach a ref to the underlying SVG element. Useful when you need programmatic access to the DOM node, for example to measure it or trigger animations.
What does memo wrapping do?
React.memo wraps the component so it only re-renders when its props change. This is a performance optimization for icon components that receive the same props on most renders.
Is anything sent to a server?
No. The conversion runs in your browser using JavaScript. No SVG data is transmitted.