React SVG Icons with vite-svgr

By the Axialis Engineering team ·

React SVG Icons with vite-svgr

Shipping raw <img> icons in React costs you CSS theming, accessibility props, and tree-shaking, and dropping inline SVG into JSX bloats your components. The fix is SVGR: import a .svg file and get back a real React component you can style with currentColor, pass className and title to, and bundle only where it is used.

This guide wires up vite-plugin-svgr for a Vite project and @svgr/webpack for Next.js, adds the TypeScript module declarations both need, and starts from a minified IconVectors SVG that already paints with currentColor and keeps a clean viewBox.

Export a clean, themable SVG from IconVectors

  1. Open or create your icon:
    • File → Open… (Ctrl+O) or New Icon (Ctrl+N).
    • Set fills/strokes to currentColor so the icon inherits CSS/text color in React.
    A 24x24 camera icon open in the IconVectors editor, with the grid, layer list, and pixel/vector preview
    Export a minified SVG via File → Export → Export Minified (Shift+Ctrl+M) to strip metadata and keep a clean viewBox.

Vite (React + TypeScript): install & configure SVGR

  1. Install
    npm i -D vite-plugin-svgr
    # or: pnpm add -D vite-plugin-svgr
    # or:  yarn add -D vite-plugin-svgr
  2. Configure vite.config.ts
    import { defineConfig } from 'vite'
    import react from '@vitejs/plugin-react'
    import svgr from 'vite-plugin-svgr'
    
    export default defineConfig({
      plugins: [
        react(),
        svgr({
          svgrOptions: {
            // Keep viewBox for proper scaling; strip width/height
            svgo: true,
            svgoConfig: {
              plugins: [
                { name: 'preset-default', params: { overrides: { removeViewBox: false } } },
                'removeDimensions'
              ]
            },
            titleProp: true
          }
        })
      ]
    })
  3. Add TypeScript types (project root)
    // env.d.ts
    /// <reference types="vite/client" />
    declare module '*.svg?react' {
      import * as React from 'react'
      const Component: React.FC<React.SVGProps<SVGSVGElement> & { title?: string }>
      export default Component
    }
  4. Import & use
    import CheckIcon from './icons/check.svg?react'
    
    export function Button() {
      return (
        <button className="inline-flex items-center gap-2 text-blue-600 hover:text-blue-700">
          <CheckIcon className="w-5 h-5" aria-hidden="true" />
          Save
        </button>
      )
    }

    Theming: because the SVG paints with currentColor, the icon inherits the button's text color. Override it with a utility class such as text-rose-600 or an inline style={{ color: '#2563eb' }}.

Next.js: configure SVGR and import SVG components

  1. Install
    npm i -D @svgr/webpack
    # (Next already includes SVGO; we'll keep viewBox and remove width/height)
  2. Configure next.config.js
    /** @type {import('next').NextConfig} */
    const nextConfig = {
      webpack(config) {
        // Let SVGR handle .svg imports as React components
        config.module.rules.push({
          test: /\.svg$/i,
          issuer: /\.[jt]sx?$/,
          use: [{
            loader: '@svgr/webpack',
            options: {
              svgo: true,
              svgoConfig: {
                plugins: [
                  { name: 'preset-default', params: { overrides: { removeViewBox: false } } },
                  'removeDimensions'
                ]
              },
              titleProp: true
            }
          }]
        })
        return config
      }
    }
    module.exports = nextConfig
  3. Add TypeScript types (project root)
    // svg.d.ts
    declare module '*.svg' {
      import * as React from 'react'
      const Component: React.FC<React.SVGProps<SVGSVGElement> & { title?: string }>
      export default Component
    }
  4. Import & use
    import CheckIcon from '@/icons/check.svg'
    
    export default function Page() {
      return (
        <main className="p-6 text-emerald-600">
          <h1 className="text-xl font-semibold flex items-center gap-2">
            <CheckIcon className="w-6 h-6" aria-hidden="true" />
            Profile updated
          </h1>
        </main>
      )
    }

Tree-shaking & project structure

Troubleshooting

Related guides

Start Making SVG Icons Today with IconVectors

Download the fully-functional 30‑Day Free Trial and unlock your icon design workflow.

Version 1.70 for Windows and macOS