There are five ways to use SVG in React: paste it inline as JSX, import it as a component with SVGR, point an img tag at the file, reference a sprite with use, or pass it to next/image in Next.js. For interface icons, an inline component is usually right, because it takes its colour from CSS and its size from your layout. Turning an SVG into a React component means three changes: rename the attributes JSX won't accept (class to className, stroke-width to strokeWidth), strip what the design tool left behind, and swap fixed colours for currentColor. For one file, my free SVG to JSX converter does all of it in your browser. For a folder of icons, use SVGR in your build.
I'm a design engineer: I design products and build them in React and Next.js, and I built that converter because I was cleaning the same Figma exports by hand every week. I checked every API and option below against its official docs on 1 November 2026.
The five ways to use SVG in React
| Way | Recolour with CSS | Cached as its own file | Best for |
|---|---|---|---|
| Inline JSX component | Yes | No, it's in your JavaScript | Interface icons |
SVGR import (import Icon from "./icon.svg") | Yes | No | Many icons kept as .svg files |
<img src="/logo.svg" /> | No | Yes | Logos, illustrations |
Sprite with <use href="#id" /> | Partly | Yes, if external | Hundreds of icons |
next/image | No | Yes | Large SVG artwork in Next.js |
A sixth option, a data URI in a CSS background-image, suits small decorative shapes that never need a label.
1. Inline JSX
You paste the SVG into a component and fix the attributes. Here is a typical export from a design tool:
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<title>Arrow / Right</title>
<g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(3, 5)" stroke="#0F0F0F" stroke-width="1.5" stroke-linecap="round">
<line x1="0" y1="7" x2="17" y2="7"></line>
<polyline points="10.5 0.5 17 7 10.5 13.5"></polyline>
</g>
</g>
</svg>And the same icon as a clean React component in TypeScript:
import type { SVGProps } from "react";
export function ArrowRight(props: SVGProps<SVGSVGElement>) {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5}
strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}>
<path d="M3 12h17M13.5 5.5 20 12l-6.5 6.5" />
</svg>
);
}The XML declaration, the editor groups, the fixed size and the hard-coded colour are gone, and {...props} lets you pass className, onClick or an aria-label from outside: <ArrowRight className="size-5" />.
2. SVGR
SVGR turns .svg files into React components, from the command line or inside your bundler. For a folder of icons, the CLI writes one component per file:
npx @svgr/cli --icon --typescript --out-dir src/icons -- assets/iconsIts options include --icon (sizes the icon to 1em), --typescript, --title-prop (adds a title prop for accessible names), --replace-attr-values (for example #0F0F0F=currentColor) and --native for React Native. SVGO runs by default.
In Next.js, SVGR's Next.js guide adds @svgr/webpack to the webpack config, so import Star from "./star.svg" gives a component and import starUrl from "./star.svg?url" still gives a URL. With Turbopack, the Next.js turbopack docs list @svgr/webpack among tested loaders and show a rule mapping *.svg to it with as: '*.js'.
3. A plain img tag
<img src="/illustration.svg" alt="..." /> is the simplest and often the best choice for a large drawing: the browser caches it and your JavaScript stays small. The cost is control. CSS on your page can't reach inside the file, so you can't recolour it, and MDN's SVG as an image notes that scripts are disabled and external images and stylesheets won't load in that context.
4. A sprite with use
Define each icon once as a symbol and draw it with <svg><use href="/icons.svg#arrow" /></svg>. MDN's use element page carries two warnings: browsers may refuse a cross-origin href, so host the sprite on your own domain, and the cloned shapes aren't guaranteed to inherit CSS, so leave fill and stroke unset inside the symbol (or set them to currentColor) if you want to colour them from outside.
5. next/image
The Next.js Image docs say Next.js doesn't optimise SVG by default, because it's a vector format and because SVG can carry the same risks as HTML. When src ends in .svg, the image is served unoptimized automatically. To push SVG through the optimiser you need dangerouslyAllowSVG, and the docs strongly recommend pairing it with contentDispositionType: 'attachment' and a contentSecurityPolicy that blocks scripts. For icons, next/image gains you nothing over an inline component, and you lose CSS colour.
SVG to JSX: what has to change
React's JSX guide explains the rule: attributes become JavaScript object keys, so they're written in camelCase, and class, a reserved word, becomes className. The ones that come up in every SVG:
| In the .svg file | In JSX |
|---|---|
class | className |
stroke-width, stroke-linecap, stroke-linejoin | strokeWidth, strokeLinecap, strokeLinejoin |
fill-rule, clip-rule | fillRule, clipRule |
clip-path, stop-color, font-size | clipPath, stopColor, fontSize |
xlink:href | href |
style="fill: red" | style={{ fill: "red" }} |
aria-label, data-name | unchanged |
The guide also says aria-* and data-* keep their dashes "for historical reasons". If you get a name wrong, React warns in the console and suggests the right one.
Also remove what JSX can't take or doesn't need: the <?xml ?> declaration, comments, xmlns:xlink when nothing uses it, and the ids your layers panel added.
currentColor for theming
MDN defines `currentColor` as the value of the element's color property. Put fill="currentColor" or stroke="currentColor" in the icon, and it takes the colour of the text around it. One icon then works on a light button, a dark nav bar and in a hover state, with no extra props.
Two cautions. A multi-colour icon, such as a flag or a brand mark, loses its colours if you turn them all into currentColor; keep those as they are. And if your design system names colours as tokens, apply them through color on the parent rather than through a fill prop on each icon. My post on design tokens covers how I name and ship those.
Size from the viewBox, not width and height
Drop the fixed width and height and keep the viewBox. The icon then fills whatever box your CSS gives it and keeps its proportions. If an SVG has no viewBox, make one from its width and height (0 0 24 24 for a 24 by 24 icon) before you remove them, or it won't scale.
SVGO: make it smaller first
SVGO removes editor metadata, comments, empty groups, unused ids and needless precision in path data. Its preset-default runs 33 plugins. The v3 to v4 migration notes say removeViewBox and removeTitle are no longer in the default preset, "to preserve scalability" and "to preserve accessibility". If you're on SVGO 3 or an old config, check that your icons still have a viewBox after optimising. From the command line, npx svgo icon.svg -o icon.min.svg does one file.
SVG in React Native
React Native has no svg element. You need react-native-svg: npx expo install react-native-svg in Expo, or npm install react-native-svg and pod install in a bare app. Elements are imported by name, Svg, Path, G, Circle, and used like the web version.
Its usage guide covers the other routes: SvgXml renders an SVG string, SvgCss handles SVGs with style blocks, SvgUri loads a remote file, and react-native-svg-transformer lets you import .svg files as components after a change to metro.config.js. SVGR's --native flag writes components for react-native-svg too.
Pitfalls I see most often
- Clashing ids. Two inline icons that both define a gradient or clip path with
id="a"will draw with whichever came first. Give ids unique prefixes, or remove the defs you don't need. - Huge illustrations inline. Every path ends up in your JavaScript bundle. Over a few kilobytes, an
imgis usually better. - Untrusted SVG. An SVG can carry scripts, event handlers and
javascript:links. Never drop a file from an unknown source intodangerouslySetInnerHTML. - A forgotten fixed colour. One
stroke="#0F0F0F"left on an inner group, and the icon ignores dark mode.
Alternatives, honestly
- Icon packages. If the icon comes from a public set, its React package, such as lucide-react, is quicker than converting.
- SVGR's [playground](https://react-svgr.com/playground/) converts one SVG online, with SVGR's options as switches.
- [transform.tools](https://transform.tools/html-to-jsx) is the HTML and SVG to JSX converter React's own guide points to.
- [SVGOMG](https://svgomg.net/) is a visual front end for SVGO, if you only need a smaller file.
- By hand, with the table above, for a single simple icon.
How my free SVG to JSX converter does it
My SVG to JSX converter turns an SVG into a React component in one step, and it runs entirely in your browser, so nothing is uploaded.
- Paste or drop an .svg file. The component is named after the file.
- Optimise with SVGO using the default preset, run until nothing more shrinks. The
viewBoxis always kept, and the tool shows the bytes saved. - Rewrite for JSX. Every attribute gets its JSX name, style strings become style objects, text is escaped and props are spread onto the root.
- Use currentColor swaps solid colours for
currentColor, with a live test colour in the preview. It warns you when the SVG has more than one colour. - Keep width and height off lets the icon size itself from its
viewBox; if there isn't one, it's made from the width and height. - Hide from screen readers adds
aria-hiddenand drops thetitle. Turn it off for an icon that carries meaning, and thetitlestays as its name. - Choose the output: React in TypeScript or JavaScript, React Native for react-native-svg (style blocks, titles and class names left out), clean SVG, a data URI in URL-encoded and base64 form, or CSS.
It also removes scripts, event handlers and javascript: links before anything is shown or written. Even so, only ship files from sources you trust.
Frequently asked questions
How do I convert an SVG to a React component?
Rename attributes to camelCase, change class to className, remove the XML declaration and editor leftovers, and wrap the result in a function that spreads props onto the svg. A converter such as my SVG to JSX tool or SVGR does it for you.
Should I use inline SVG or an img tag in React?
Inline (or SVGR) for icons you want to colour and size with CSS. An img tag for large illustrations and logos, which the browser can cache and which keep your JavaScript small.
Why do I get "Invalid DOM property stroke-width"?
Because JSX needs strokeWidth. Every dashed SVG attribute except aria-* and data-* takes its camelCase name in React.
How do I change an SVG icon's colour in React?
Set its fill or stroke to currentColor and change the CSS color on the icon or its parent, for example with a Tailwind text-* class.
Can I import .svg files directly in Next.js?
As a URL, yes. As a component, add @svgr/webpack: through the webpack config, or as a Turbopack rule for *.svg.
How do I use SVG in React Native?
Install react-native-svg and use its Svg, Path and other components, or SvgXml for an SVG string. My converter's React Native tab writes the component for you.
Sources and method
I read every source on 1 November 2026 and checked the tool's behaviour against its own code and page copy.
- React, Writing markup with JSX, date read 1 November 2026: react.dev
- SVGR, getting started, options, CLI and Next.js guides, date read 1 November 2026: react-svgr.com
- Next.js, Image component, dangerouslyAllowSVG, date read 1 November 2026: nextjs.org
- Next.js, turbopack configuration, webpack loaders, date read 1 November 2026: nextjs.org
- MDN, SVG as an image, date read 1 November 2026: developer.mozilla.org
- MDN, the use element, date read 1 November 2026: developer.mozilla.org
- MDN, the title element, date read 1 November 2026: developer.mozilla.org
- MDN, currentColor keyword, date read 1 November 2026: developer.mozilla.org
- SVGO, preset-default and migration from v3 to v4, date read 1 November 2026: svgo.dev
- react-native-svg, README and usage guide, date read 1 November 2026: github.com
Icons are the small part of a front end. If you want the rest designed and built in React and Next.js from the same Figma file, see my development work or book a free 30 minute intro call.
Tags: React, SVG, SVGR, Icons, Free tools



