DEV Community

Cover image for Import SVGs as React component and set color in CSS with currentColor
Andreas Riedmüller
Andreas Riedmüller

Posted on • Edited on

Import SVGs as React component and set color in CSS with currentColor

There are two ways to display an SVG graphic on a webpage: by creating an img tag that points to the SVG file, or by directly embedding the SVG code in the HTML. The latter method gives you more control over the SVG, and is particularly useful when you want to use CSS to change the color of the SVG.

To do this, you can use the currentColor value in the SVG code, which allows the element to inherit the text color set by CSS. However, this technique only works if the SVG code is part of the DOM.

<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
  <circle cx="5" cy="5" r="5" fill="currentColor"/>
</svg>
Enter fullscreen mode Exit fullscreen mode

I recently learned that it’s quite easy to embed SVG from a file in your React project.

If you import a SVG file most bundlers will return just a URL to the SVG file.

// Import
import svgIcon from './icon.svg'

// Usage in JSX
<img src={svgIcon} alt="Circle" />
Enter fullscreen mode Exit fullscreen mode

But you can use SVGR to get the SVG markup into your DOM. SVGR is installed per default when using CRA, but there are also plugins for other tools.

// Import (SVGR has to be installed)
import { ReactComponent as SvgIcon } from './icon.svg'

// Usage in JSX
<SvgIcon />
// Usage with custom class and width
<SvgIcon className="my-class" width="42" />
Enter fullscreen mode Exit fullscreen mode

Vite

While this works out of the box for Create React App projects, you need to install vite-plugin-svgr if you are using Vite.

// vite.config.js
import svgr from "vite-plugin-svgr";

export default {
  // ...
  plugins: [svgr(), react()],
};
Enter fullscreen mode Exit fullscreen mode

If you are using typescript you might as well need to add the missing types in tsconfig.json:

"compilerOptions": {
  ...
  "types": [
    "vite-plugin-svgr/client"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Gatsby

And you can easily get this to work in Gatsby as well by installing this SVGR plugin for Gatsby.

npm install @svgr/webpack gatsby-plugin-svgr
Enter fullscreen mode Exit fullscreen mode

Then add it to your Gatsby config:

// gatsby-config.js
module.exports = {
  plugins: [
    'gatsby-plugin-svgr',
  ],
}
Enter fullscreen mode Exit fullscreen mode

That's it, you can now give classes to SVG elements, style them with CSS or use currentColor.

Here is the link to the CRA docs:
https://create-react-app.dev/docs/adding-images-fonts-and-files/#adding-svgs

Top comments (3)

Collapse
 
techman09 profile image
TechMan09

Interesting! I’ve always been manually defining SVG colors, maybe it’s time for a change…

Collapse
 
landsman profile image
Michal

Disclaimer: This approach is really bad for browser cache. When you move svg source code to the DOM, you lose all the benefits of browser cache.

Collapse
 
receter profile image
Andreas Riedmüller

If you use SSR you should always have an eye on your document size. If it gets to large one thing to look out for are embedded images (Data URLs) or inline SVGs as you said. The same is true for the Javascript bundle size.

If you use React (without SSR) your code will be injected into the DOM via Javascript and the SVG data is inside your Javascript bundle that is cached by your browser.

Most of the time I use this feature for relatively small SVGs. For big SVG files features like currentColor are often not needed an it is better to use an <img>.

But even then, some bundlers encode small images/svgs by default, so they would end up in your bundle anyway.