The Complete Guide to Importing SVGs in React and Vite Apps

SVGs, or scalable vector graphics, offer many advantages over raster image formats like PNG or JPG. Their resolution-independence makes them ideal for responsive web design, while their small file size helps boost page load speed. SVGs are also highly customizable via CSS and can even be animated. As a result, SVGs have become the go-to format for icons, logos, and illustrations on the modern web.

But working with SVGs in a React application is not always straightforward, especially if you are using a bundler like webpack or a build tool like Vite. In this in-depth guide, we‘ll explore all the different ways you can import and use SVGs in your React and Vite projects. By the end, you‘ll have a full understanding of SVG usage in React and be able to choose the optimal approach for your needs.

Method 1: Using the <img> Tag

The simplest way to display an SVG in React is to import it and use it as the src for an <img> tag:

import React from ‘react‘;
import logo from ‘./logo.svg‘;

function Header() {
  return (
    <header>
      <img src={logo} alt="Logo" />
    </header>
  )
}

export default Header;

This works out of the box in projects bootstrapped with Create React App (CRA). Under the hood, CRA configures webpack with a file loader that handles SVG imports.

However, if you‘re not using CRA, you‘ll need to set up the file loader yourself. First, install it:

npm install file-loader --save-dev

Then add a rule for SVGs to your webpack config:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: ‘file-loader‘,
          },
        ],
      },
    ],
  },
};

Now SVGs can be imported and used in img tags just like in CRA projects.

The main limitation of this method is that it doesn‘t allow you to style or modify the SVG using CSS. The SVG file is loaded as an external image resource, so its internals are not exposed to the DOM.

Method 2: Inline JSX

Since SVGs are just XML, you can copy and paste their markup directly into your React components:

function Icon() {
  return (
    <svg viewBox="0 0 100 100">
      <circle cx="50" cy="50" r="40" stroke="black" strokeWidth="3" fill="red" />
    </svg>
  );
}

The advantage here is that the SVG is now part of the DOM, so you can target its elements with CSS to change its appearance. You could use props to dynamically change styles as well:

function Icon({ color, size }) {
  return (
    <svg viewBox="0 0 100 100" width={size} height={size}>
      <circle cx="50" cy="50" r="40" stroke="black" strokeWidth="3" fill={color} />
    </svg>
  );
}

The main drawbacks are:

  1. Inlining large, complex SVGs will bloat your component code and make it harder to read.

  2. If the same SVG is used in multiple places, its markup will be duplicated each time, increasing bundle size.

  3. You have to manually convert SVG markup to JSX by replacing hyphens with camelCase (stroke-width becomes strokeWidth), using self-closing tags (<path /> not <path></path>), etc. Some online converters can help with this.

Method 3: Importing as React Components

A popular approach is to import SVGs as React components:

import { ReactComponent as Logo } from ‘./logo.svg‘;

function Header() {
  return (
    <header>
      <Logo />
    </header> 
  );
}

This syntax is enabled by SVGR, an SVG transforming tool. It converts your SVG files into React components, handling the JSX conversion and allowing you to use them like any other component.

To use this in a non-CRA project, first install SVGR‘s webpack loader:

npm install --save-dev @svgr/webpack

Then update your webpack config:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [‘@svgr/webpack‘],
      },
    ],
  },
};

Now you can import SVGs as React components. The imported components accept all normal SVG element props for customizing their appearance and behavior.

Method 4: Manual Component Conversion

You can perform the SVG-to-component conversion yourself if you don‘t want to set up SVGR. Create a new component file, paste in the SVG markup, and make the necessary JSX changes:

// Logo.js
function Logo() {
  return (
    <svg viewBox="0 0 100 100">
      <circle cx="50" cy="50" r="40" stroke="black" strokeWidth="3" fill="red" />
    </svg>
  );
}

export default Logo;

Then import and use the Logo component:

import Logo from ‘./Logo‘;

function Header() {
  return (
    <header>
      <Logo />
    </header>
  );
}

This gives you full control but requires more manual effort, especially if you have many SVGs to convert. Keeping the SVG markup in separate files also makes them easier to update than with the inline approach.

Method 5: Using SVGR CLI

SVGR also provides a CLI for converting SVGs to components without configuring a bundler. First, install the CLI globally:

npm install -g @svgr/cli 

Then run it on your SVG file(s):

svgr --icon --replace-attr-values "#000=currentColor" icon.svg

This outputs a icon.js React component file. The CLI has many options for customizing the output.

Running the CLI each time you want to convert an SVG can be tedious. You may want to set up a watch script to automatically convert SVGs as you add them to your project.

Method 6: Using Vite Plugin

If you‘re using Vite instead of webpack, you can leverage the vite-plugin-svgr plugin. It uses SVGR under the hood but is designed to work seamlessly with Vite‘s plugin system.

Install the plugin:

npm i vite-plugin-svgr

Then add it to your vite.config.js:

import { defineConfig } from ‘vite‘
import svgr from ‘vite-plugin-svgr‘

export default defineConfig({
  plugins: [svgr()],
})

Now you can import SVGs as React components just like with the SVGR webpack loader:

import { ReactComponent as Logo } from ‘./logo.svg‘;

Which Approach Should You Use?

With all these options, which one should you reach for in your projects? It depends on your specific needs and constraints:

  • Use the img tag method if you just need to display SVGs and don‘t need to style them.

  • Use inline JSX for one-off, highly customized SVGs that don‘t repeat in your app.

  • Use imported React components (via SVGR or manual conversion) for reusable, customizable SVGs.

  • Use Vite plugin if you‘re already using Vite in your project.

  • Avoid manual conversion for more than a handful of SVGs, as it quickly becomes tedious.

In most cases, importing SVGs as React components provides the best balance of convenience and flexibility. You get easy reuse, styling via props, and automatic conversion with SVGR.

Conclusion

Working with SVGs in React may seem daunting at first, but armed with the right tools and techniques, you can leverage their full potential. Whether you use a ready-made solution like CRA or Vite plugin, or set up your own pipeline with SVGR and webpack, the key is understanding how to prepare SVGs for use in your React components.

I hope this guide has clarified the different approaches and their tradeoffs. Remember, there‘s no one "right" way—choose the method that best fits your project‘s setup and requirements. Happy SVG coding!

Further Reading

Want to dive deeper into SVGs in React? Check out these resources:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *