DEV Community

Tommy Ju
Tommy Ju

Posted on

Making SVGs Customizable with CSS in Next.js (2026)

Introduction

Are you confused by SVG icons that refuse to be styled with CSS?

This article will give you a scalable workflow for styling SVG icons in your Next.js project.

We will address the problems of:

  • CSS properties not applying to static SVG images
  • Hard-coded attributes within SVG files that overwrite CSS properties

(The steps in this guide are specifically for Next.js v16+ and Typescript, but the concepts also apply to general React projects)

Why CSS Doesn't Work on Static SVGs

When you try to use an SVG like this:

<img src="your_icon.svg" className="icon" />

# or

<Image
    src="your_icon.svg"
    alt="GitHub"
    width={48}
    height={48}
    className="icon"
/>

Enter fullscreen mode Exit fullscreen mode

The SVG is treated as a static external image file, similar to a PNG or JPG. You can resize it, but you cannot style or animate the contents with CSS. The root cause is not the <img> or <Image> tag itself, but the fact that the SVG is being loaded from the public/ directory which is specifically meant for static assets.

Solution

To make our SVGs customizable with CSS, we will convert them to React components using SVGR and move them out of the the /public directory:

  1. Install SVGR as a dev dependency

    npm install --save-dev @svgr/webpack
    # or use yarn
    yarn add --dev @svgr/webpack
    
  2. Configure SVGR in next.config.ts

    import type { NextConfig } from "next";
    
    const nextConfig: NextConfig = {
      /* config options here */
    
      turbopack: {
        rules: {
          "*.svg": {
            loaders: ["@svgr/webpack"],
            as: "*.js",
          },
        },
      },
    };
    
    export default nextConfig;
    

    We are using the TurboPack asset bundler which is the fully supported default in Next.js v16.

  3. Use the SVG in your code as follows, you must ensure that the SVG is not stored in /public.

    import GithubIcon from "@/icons/github.svg";
    
    export default function ExternalLinks() {
    
        return (
            <GithubIcon
                width={24}
                height={24}
                className="icon"
            />
        );
    }
    

Congratulations! Your SVG is now a React component rendered in the DOM as JSX, rather than a static file in /public. This makes it fully styleable, interactive, and dynamic.

Cleaning Hard-Coded SVG Attributes that Overwrite CSS

Some SVGs may contain hard-coded attributes that overwrite your CSS styles. In the following image, the LinkedIn icon refuses to be any color other than black.

SVG image with hard-coded attributes

If you open the SVG file in your text editor, you can confirm this by looking for hard-coded attributes such as fill, stroke, and style:

<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">

<!-- Hard-coded fill attribute prevents color changes with CSS -->
<path d="..." fill="#0F0F0F"/>

</svg>
Enter fullscreen mode Exit fullscreen mode

Solution

For smaller projects you can manually replace or remove hard-coded attributes that affect the appearance of the SVG.

However, this may be time consuming if you have many SVG files. Here's how you can automate this process using SVGO.

We will modify the SVG to inherit its color from CSS via the color property, making it compatible with both plain CSS and utility frameworks like Tailwind.

  1. Install SVGO as a dev dependency

     npm install -D svgo
    
  2. Create a file in the root directory called svgo.config.js with the following code

    module.exports = {
      plugins: [
        {
          name: "preset-default",
          params: {
            overrides: {
              removeViewBox: false, // keep viewBox for proper scaling
            },
          },
        },
    
        // Remove hard-coded fill, stroke, and style attributes
        {
          name: "removeAttrs",
          params: {
            attrs: "(fill|stroke|style)",
          },
        },
    
        // Add fill="currentColor" to the root <svg>
        {
          name: "addAttributesToSVGElement",
          params: {
            attributes: [
              { fill: "currentColor" }
            ],
          },
        },
      ],
    };
    
  3. Add a script in package.json for cleaning the SVG files, ensure that the path points to the location where your SVG files are stored

    "scripts": {
      "clean-icons": "svgo --config=svgo.config.js [PATH_TO_SVG_DIRECTORY]/*.svg"
    },
    
    
  4. Run the script to automatically modify the hard-coded attributes from your SVG files that overwrite your CSS

    npm run clean-icons
    

Conclusion

By converting your SVGs to React components with SVGR and cleaning hard-coded attributes with SVGO, you can create fully dynamic, styleable, and maintainable icons in Next.js. This workflow ensures your SVGs respond to CSS, support animations, and remain scalable.

Feel free to adapt this workflow to your own projects and share any tips or improvements you discover along the way!

Top comments (0)