DEV Community

Cover image for Stop Using <img> for SVGs in React: A Better Way with SVGR
Dipanwita Bala
Dipanwita Bala

Posted on

Stop Using <img> for SVGs in React: A Better Way with SVGR

For a long time, I used SVGs in the most straightforward ways possible. I would either download SVG images and use them directly, or copy the SVG code and turn it into a custom React component.

Using downloaded SVG images gave me very little control. If I needed different variants of the same icon—for example, a different color for dark mode or hover states—I had to download multiple versions of the same SVG. This quickly became repetitive and hard to maintain.

The second approach—copying the SVG code and creating a React component—was definitely better. It allowed me to customize the SVG using props and CSS. However, this came with its own drawbacks. I had to manually create a component for every SVG, and in many cases, the SVG source code wasn’t even available or was messy to work with.

We all know SVGs are great for the web. They are scalable, lightweight, flexible, and offer fine-grained control. Since SVGs are essentially XML, they can be animated with CSS or JavaScript and manipulated directly in the DOM.

But as beginners, we often don’t know how to use SVGs in an optimized way or how to unlock their full potential in real-world projects.

The most common approach most of us start with looks like this:

<img src="path-to-svg-file.svg" alt="svg image" />
Enter fullscreen mode Exit fullscreen mode

This works, but it has serious limitations. SVGs used this way cannot respond to theme changes, CSS-based coloring, hover states, or animations properly.

A better approach is to create React components using the SVG markup directly:

export const CancelIcon = () => {
  return (
    <svg 
      xmlns="http://www.w3.org/2000/svg" 
      fill="none" 
      viewBox="0 0 24 24" 
      strokeWidth="1.5" 
      stroke="currentColor"
    >
      <path 
        strokeLinecap="round" 
        strokeLinejoin="round" 
        d="M6 18 18 6M6 6l12 12" 
      />
    </svg>
  );
};
Enter fullscreen mode Exit fullscreen mode

This approach is much better. It allows theme-based coloring, animations, and styling using CSS or Tailwind. However, the downside is that you still have to manually create a component for every SVG you use, which becomes tedious as your project grows.

This is where SVGR comes in.

With SVGR, SVG files can be imported directly as React components:

import Icon from "@/assets/icon.svg";
Enter fullscreen mode Exit fullscreen mode

And used like this:

<Icon className="w-6 h-6 text-lime-400" />
Enter fullscreen mode Exit fullscreen mode

This instantly unlocks:

  • Theme-based coloring
  • CSS and Tailwind animations
  • Hover and active states
  • Cleaner and more maintainable code

How to use SVGR in your project

SVGR setup

1. Install the package

npm install --save-dev @svgr/webpack
Enter fullscreen mode Exit fullscreen mode

2. Configure Next.js

Add the following to your next.config.ts file:

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack(config: any) {
    config.module.rules.push({
      test: /\.svg$/,
      issuer: /\.[jt]sx?$/,
      use: [
        {
          loader: "@svgr/webpack",
          options: {
            icon: true,
            svgo: true,
            svgoConfig: {
              plugins: [
                {
                  name: "removeViewBox",
                  active: false,
                },
              ],
            },
          },
        },
      ],
    });

    return config;
  },
};

module.exports = nextConfig;
Enter fullscreen mode Exit fullscreen mode

3. Important note about Webpack and Turbopack

SVGR currently relies on Webpack.

If you are using Next.js 16, Turbopack is enabled by default, and you may see this error:

"This build is using Turbopack, with a webpack config and no turbopack config."

This is not a bug—it’s a tooling tradeoff. You can either silence the warning or explicitly tell Next.js to use Webpack.

Update your package.json:

"dev": "next dev --webpack"
Enter fullscreen mode Exit fullscreen mode

And you’re good to go.


Important things to keep in mind

  1. Store your SVG files inside a folder within the app directory so they can be imported properly.
  2. Open the SVG file in a text editor and ensure the color is not hardcoded. Use currentColor instead:
<svg fill="currentColor" stroke="currentColor">
Enter fullscreen mode Exit fullscreen mode

This allows the SVG to inherit color from CSS or Tailwind classes.

Once this is set up, you can import SVGs as components and freely apply styles, animations, and theme-based colors.

If you face any issues or have questions, feel free to reach out.
Happy coding!

Top comments (0)