Editor’s note: This article was last updated on 12 December 2022 to add a section about how to inject SVGs to the DOM using the react-svg component, as well as ensuring compatibility with the latest version of react-svg (12.1.13 at the time of writing).
SVG is a vector graphics image format based on XML. SVG stands for Scalable Vector Graphics. It was developed in the late 1990s and was poorly supported until around 2016.
Today, a huge percentage of icon libraries, such as Flaticon, Font Awesome, Material Icon, etc., have full support for SVG. Brands such as Twitter, YouTube, Udacity, Netflix, and more use SVG for some of their images and icons.
We’ll cover the following:
You’re probably more familiar with image formats like JPEG, GIFs, and PNG than you are with SVG. However, there are many reasons why you’d want to use SVG over these other formats. Let’s look at some advantages that SVGs have over other image formats:
fill
instead of color
, for example. You can also style SVG with CSS. Likewise, because SVGs are DOM-like, SVGs can be created, edited, and animated with any text editor
Below we’ll go through various ways we can use or render this React SVG logo on a webpage.
It is worth noting that Create React App has a built-in configuration for handling SVGs. Some of the examples in this article that require modifying the webpack setup are applicable only to custom React projects using webpack as a bundler.
You may need different plugins if you don’t use webpack for your custom React project.
<img>
tag for static SVGsIn order to use SVGs or any other image format in the <img>
tag, we have to set up a file loader system in whichever module bundler we’re using. Here, I will show you how to set it up in a few steps if you are already using webpack as your bundler.
If you are using webpack 4, first install the file-loader library with the command $ npm install file-loader --save-dev
. This will install it as a dev dependency.
You can update your webpack configuration file rules with this code:
const webpack = require('webpack'); module.exports = { entry: './src/index.js', module: { rules: [ //... { test: /\.(png|jp(e*)g|svg|gif)$/, use: [ { loader: 'file-loader', options: { name: 'images/[hash]-[name].[ext]', }, }, ], }, ], }, //... };
However, the file-loader library is deprecated if you are using webpack 5. Use asset modules instead. With asset modules, you can use asset files in your project setup without installing additional loaders. Update the rules field of your webpack configuration file to include the following:
module.exports = { entry: "./src/index.js", module: { rules: [ //... { test: /\.(png|jp(e*)g|svg|gif)$/, type: "asset/resource", }, ], }, //... };
Now you can import your SVG and use it as a variable, like this:
import React from 'react'; {/*images*/} import ReactLogo from './logo.svg'; const App = () => { return ( <div className="App"> <img src={ReactLogo} alt="React Logo" /> </div> ); } export default App;
<svg>
elementWith the same webpack settings above, we can use the <svg>
element by copying and pasting the contents of the .svg
file into our code. Here is a sample use case:
import React from 'react'; const App = () => { return ( <div className="App"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"> <g fill="#61DAFB"> <path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/> <circle cx="420.9" cy="296.5" r="45.7"/> <path d="M520.5 78.1z"/> </g> </svg> </div> ); } export default App;
You can likely already see the disadvantage of using this method. When the image is more complex, the SVG file becomes larger, and because SVG is stored in text, that means we have a whole bunch of text in our code.
SVGs can be imported and used directly as a React component in your React code. The image is not loaded as a separate file; rather, it’s rendered along with the HTML. A sample use case would look like this:
import React from 'react'; import {ReactComponent as ReactLogo} from './logo.svg'; const App = () => { return ( <div className="App"> <ReactLogo /> </div> ); } export default App;
Note that this approach only works with Create React App. CRA uses SVGR under the hood to make it possible to transform and import an SVG as a React component. If you’re not using Create React App, I would recommend using other approaches.
SVGR is an awesome tool that converts your SVGs into React components. So how do we set it up?
First, install the package by running the command $ npm install @svgr/webpack --save-dev
. Then, update your webpack configuration rule to use SVGR for SVGs:
const webpack = require('webpack'); module.exports = { entry: './src/index.js', module: { rules: [ //... { test: /\.svg$/, use: ['@svgr/webpack'], }, ], }, //... };
Now you can import SVG images as React components and use them in our code like so:
import React from 'react'; import ReactLogo from './logo.svg'; const App = () => { return ( <div className="App"> <ReactLogo /> </div> ); } export default App;
Data URLs are URLs prefixed with the data:
scheme, which allows content creators to embed small files inline in documents. You can read more about them in the MDN web docs. This approach allows us to use SVG images like an inline element.
How do you achieve this? First, you’ll need an appropriate loader if you are using webpack. For this use case, I’ll use svg-url-loader
. You can add it your project by running the command $ npm install svg-url-loader --save-dev
.
Then, update the webpack configuration file rules section with the following:
const webpack = require('webpack'); module.exports = { entry: './src/index.js', module: { rules: [ //... { test: /\.svg$/, use: [ { loader: 'svg-url-loader', options: { limit: 10000, }, }, ], }, ], }, //... };
Now you can import your SVG file and use it in your React component like this:
import ReactLogo from './logo.svg'; const App = () => { return ( <div className="App"> <img src={ReactLogo} alt="React Logo" /> </div> ); } <img src="data:image/svg+xml,%3csvg..." alt="React Logo" />
This usually results in something like this in the DOM:
<img src="data:image/svg+xml,%3csvg..." alt="React Logo" />
react-svg
Adding SVG markup directly in your React component increases its file size, making it hard to maintain. Despite this limitation, using inline SVG comes with its advantages. You can easily apply CSS styles to the SVG markup when you embed it inline compared to using the img
tag.
To leverage the benefits of embedding SVGs inline without worrying about the maintainability of your component, you can use the react-svg
package. It fetches the SVG asynchronously and embeds it inline.
You can install it from the NPM package registry like so:
npm install react-svg
You can then import the ReactSVG
component and render it in your React application. The ReactSVG
component takes the URL for your SVG as the value of the src
prop. It also takes several optional props you can look up in the documentation:
import { ReactSVG } from "react-svg"; <ReactSVG src="icon.svg" />
As mentioned in the introduction, one of the benefits of using SVGs over other image formats is that SVGs are possible to animate. You can animate SVGs using CSS or React animation libraries like Framer motion and React spring.
Things to note:
<svg>
element. Here, I would recommend you go with PNG or JPEG imagesSVGs make up a significant proportion of images on the web today. As highlighted above, SVGs have smaller file sizes than other image formats. You can resize them without losing image quality, and they are animatable.
Though its usage is straightforward with HTML, you need additional tools and configuration to start using SVGs in frontend frameworks like React. Most of the popular React project starter toolsets, like Create React App, Vite, and Astro, come with out-of-the-box configurations for handling static assets such as images, including SVGs.
As hinted in the article, Create React App uses the SVGR webpack loader, @svgr/webpack
, under the hood. Therefore, you can import an SVG with an import
statement and render it in your application. You can also inline the SVG markup. However, rendering SVGs inline can make your components hard to maintain.
For a custom React project that uses webpack as a bundler, you can configure the @svgr/webpack
loader to load SVGs similar to Create React App.
As you use SVGs, it is worth mentioning that complex images can have large SVG files, especially if you want to inline the SVG. Though most popular modern browsers fully support SVGs, some browsers, especially mobile browsers, do not have full support for certain SVG features.
We investigate how the modulo operator works in JavaScript and explore several real-life applications, like cyclic patterns and animations.
Ken Pickering discusses the challenges associated with uncertainty and shares insights on scaling data structures and engineering teams.
Let’s see how Solid props work to promote component reusability, exploring basic to advanced concepts for a complete understanding.
We evaluate Eleventy and Next.js and compare both static site generators in terms of performance, developer experience, scalability, and ecosystem.
11 Replies to "How to use SVGs in React"
Looks like a lot of editing of Webpack. What’s the best way to use SVG’s without ejecting?
Great article! help me a lot, thanks!
I tried this, but the SVG doesn’t show when using an image tag. I don’t know what I am missing. I installed file-loader, too.
Great article! One usage not mentioned above, using as inline background image:
.elem {
background-image: url(‘data:image/svg+xml, ……’);
}
I second, this is a great article!
Would also like to add the the object tag can be used (…)
But, more important – this article does not relate the fact that some of the methods listed here inline the SVG into the DOM – which allows developers to use CSS and JS to manipulate the SVG which is amazing !
You can use something like react-app-rewired to provide access to a webpack config file without ejecting.
“export ‘ReactComponent’ (imported as ‘ReactLogo’) was not found in ‘../static/images/icon/svg/feather–white.svg’
i go this error messages after using ReactComponent step, what should i do?
If you’re using CRA just import it as a component like in the example. All the SVGR business is handled for you already
“Then we update our Webpack configuration rule to use SVGR for SVGs”. What file is that? With witch name I need to create it?
“ With this, we can already see the disadvantage of using this method, when the image is more complex the SVG file becomes larger and since SVG is stored in text, that means we have a whole bunch of text in our code.”
What are the disadvantages? Is it solely the amount of text in the code? Or is there another disadvantage?
Thanks for sharing mate! Using SVG as a component worked like dream for me. One cool thing is that it creates an inline SVG which to which we can pass props such as className and control its presentation that way.