Ora

How to Use SVG Images in React Apps

Published in React SVG Integration 9 mins read

Incorporating SVG (Scalable Vector Graphics) images into your React applications is a highly effective way to ensure crisp, scalable visuals that look great on any device and screen resolution. Unlike raster images (like JPG, PNG), SVGs are XML-based, meaning they can be manipulated with CSS and JavaScript, offering immense flexibility for styling and animation.

Here are several common and effective methods to use SVG images in your React projects, from simple static embeds to dynamic, interactive components.

Why Use SVGs in React?

  • Scalability: SVGs are vector-based, meaning they scale infinitely without loss of quality, perfect for responsive designs.
  • Performance: Often smaller file sizes than raster images, especially for simple graphics.
  • Accessibility: Semantic SVG elements and attributes can improve accessibility.
  • Manipulability: Because they are code, SVGs can be styled with CSS and animated with JavaScript, offering rich interactive possibilities.
  • SEO Benefits: Search engines can read SVG XML, potentially aiding in indexing.

Methods for Integrating SVGs in React

React offers a spectrum of approaches for including SVGs, each with its own advantages depending on your specific needs.

1. Using the <img> Tag for Static SVGs

This is the simplest and most straightforward method, ideal for static SVG files that don't require any dynamic manipulation or styling via React props or CSS.

How to Use:

  1. Place your .svg file in your project's public folder or, if using a bundler like Webpack (configured by Create React App or Next.js), you can import it directly.
  2. Reference it using the src attribute of an <img> tag.

Example:

import React from 'react';
import MyIcon from './assets/my-icon.svg'; // Path to your SVG file

function App() {
  return (
    <div>
      <h2>Static SVG with `<img>`</h2>
      <img src={MyIcon} alt="My Custom Icon" className="icon-style" />
      <p>This method treats the SVG like any other image.</p>
    </div>
  );
}

export default App;
  • Pros: Easy to implement, familiar, good for simple display.
  • Cons: Limited styling capabilities (cannot change fill/stroke colors directly via CSS or props), not easily animatable with React.

2. Adding SVG Directly as JSX (Using the <svg> Element)

You can copy and paste the raw SVG code directly into your JSX. This provides maximum control and allows you to dynamically manipulate the SVG's properties using React props and state.

How to Use:

  1. Open your .svg file in a text editor.
  2. Copy the entire content, starting from the <svg> tag.
  3. Paste it directly into your React component's return statement.
  4. Remember to convert SVG attributes like stroke-width to their camelCase equivalents (e.g., strokeWidth) for JSX compatibility.

Example:

import React from 'react';

function CustomSVG() {
  const iconColor = "blue";
  const strokeWidth = 2;

  return (
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
      <circle cx="12" cy="12" r="10" stroke={iconColor} strokeWidth={strokeWidth}/>
      <path d="M12 8V12L15 15" stroke={iconColor} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

function App() {
  return (
    <div>
      <h2>Direct SVG in JSX</h2>
      <CustomSVG />
      <p>This allows full control and dynamic styling via props.</p>
    </div>
  );
}

export default App;
  • Pros: Full control over SVG properties, easy to style dynamically with React props, enables complex animations.
  • Cons: Can make your component code verbose, especially for complex SVGs, poor reusability if copied multiple times.

3. Using an SVG as a Component (Importing SVG as a React Component)

This method typically involves configuring your build tool (like Webpack with svgr/webpack) to treat SVG files as React components. This allows you to import an SVG and use it just like any other React component.

How to Use:

  1. Ensure your project is configured (e.g., Create React App handles this by default for .svg imports; for custom Webpack setups, you'd use @svgr/webpack).
  2. Import the SVG file. The import will often give you a React component.
  3. Render the imported component in your JSX.

Example (using SVGR-like setup):

import React from 'react';
import { ReactComponent as MyDynamicIcon } from './assets/dynamic-icon.svg'; // Specific import syntax for SVGR

function App() {
  const size = 32;
  const fillColor = 'green';

  return (
    <div>
      <h2>SVG as a React Component</h2>
      <MyDynamicIcon width={size} height={size} fill={fillColor} />
      <p>This is often the preferred method for reusable, stylable icons.</p>
    </div>
  );
}

export default App;
  • Pros: Highly reusable, component-based structure, easily accepts props for dynamic styling (e.g., fill, stroke, width), cleaner JSX.
  • Cons: Requires build tool configuration (though often handled by default in modern setups).

4. Using SVGR

SVGR is a popular tool that transforms SVG files into React components. It integrates seamlessly with build tools like Webpack and Vite. When you import an SVG file, SVGR converts it into a React component on the fly, making it one of the most widely adopted and efficient methods for managing SVGs in React.

How it works:
SVGR acts as a loader for your build system. When it encounters an .svg file import, it processes the SVG XML and generates a React component that renders that SVG.

Installation (if not already handled by your setup, e.g., for custom Webpack):

npm install @svgr/webpack --save-dev
# or
yarn add @svgr/webpack --dev

Webpack Configuration Example:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'], // This rule will transform SVG into React components
      },
      // Other rules for JavaScript, CSS, etc.
    ],
  },
};

After configuration, you can use SVGs as components as shown in the "Using an SVG as a Component" example.

  • Pros: Automates SVG-to-component conversion, highly efficient, excellent for icon libraries, allows TypeScript typings for SVG components.
  • Cons: Requires initial configuration for custom build setups.

5. Using SVG as a Data URL

You can embed the SVG content directly into your CSS or HTML as a data URL. This is particularly useful for background images or small, repeated icons, as it avoids additional HTTP requests.

How to Use:

  1. Encode your SVG content into a Base64 string or URL-encoded string. Many online tools can do this.
  2. Use it in CSS background-image property or directly in an <img> tag src.

Example (CSS):

.icon-background {
  background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2Z' fill='%23FF0000'/%3E%3C/svg%3E");
  width: 24px;
  height: 24px;
  display: inline-block;
}
  • Pros: Reduces HTTP requests, useful for small, decorative SVGs, can be used in CSS.
  • Cons: SVG code is not easily readable or modifiable once encoded, difficult to manipulate dynamically with JavaScript, increased CSS/HTML file size.

6. Injecting SVG to the DOM using react-svg

For more advanced scenarios where you need to load SVGs dynamically, manipulate them extensively after they're rendered, or handle external SVG files with more control, libraries like react-svg can be useful. It fetches the SVG, parses it, and injects it inline into the DOM.

Installation:

npm install react-svg
# or
yarn add react-svg

Example:

import React from 'react';
import { ReactSVG } from 'react-svg';

function App() {
  return (
    <div>
      <h2>Dynamic SVG with `react-svg`</h2>
      <ReactSVG src="./assets/remote-icon.svg"
                afterInjection={(error, svg) => {
                  if (error) {
                    console.error(error);
                    return;
                  }
                  console.log(svg); // The actual SVG DOM element
                  svg.setAttribute('fill', 'purple'); // Manipulate after injection
                }}
                wrapper="span"
                className="wrapper-class"
                beforeInjection={(svg) => {
                  svg.classList.add('svg-class-name');
                  svg.setAttribute('style', 'width: 50px; height: 50px;');
                }}
      />
      <p>Useful for advanced dynamic control or external SVGs.</p>
    </div>
  );
}

export default App;
  • Pros: Powerful for dynamic loading and post-injection manipulation, useful for external SVGs or CDN-hosted assets.
  • Cons: Adds a dependency, potentially more overhead than direct embedding for simple cases.

How to Animate SVGs in React

Animating SVGs in React opens up a world of possibilities for dynamic user interfaces and engaging experiences.

1. CSS Animations

For simple animations like fades, rotations, or path changes, CSS is often the most performant choice.

  • Directly in SVG: Use <animate>, <animateMotion>, <animateTransform> tags within the SVG itself (SMIL animations).
  • React Components with CSS: Apply CSS transitions and animations to SVG elements (e.g., path, circle) rendered as JSX.

Example (CSS):

// React component
<svg className="my-animated-svg" width="100" height="100">
  <circle cx="50" cy="50" r="40" className="animated-circle" />
</svg>
/* CSS file */
.my-animated-svg .animated-circle {
  fill: blue;
  transition: fill 0.3s ease-in-out, transform 0.5s ease-in-out;
}

.my-animated-svg:hover .animated-circle {
  fill: red;
  transform: scale(1.1);
}

2. JavaScript Libraries

For more complex, synchronized, or highly interactive animations, JavaScript libraries provide fine-grained control.

  • GSAP (GreenSock Animation Platform): A powerful, feature-rich animation library capable of animating virtually any property, including SVG paths, points, and transforms.
  • Framer Motion: A production-ready motion library for React, making it easy to create declarative animations and gestures.
  • React Spring: A spring-physics based animation library for React that is highly flexible and performant.
  • D3.js: Excellent for data visualization and complex SVG manipulations, though it has a steeper learning curve for animations.

Example (Framer Motion):

import React from 'react';
import { motion } from 'framer-motion';

function AnimatedCircle() {
  return (
    <motion.svg
      width="100"
      height="100"
      viewBox="0 0 100 100"
      initial={{ scale: 0 }}
      animate={{ scale: 1 }}
      transition={{ duration: 0.5 }}
    >
      <motion.circle
        cx="50"
        cy="50"
        r="40"
        fill="orange"
        animate={{ fill: ["orange", "red", "purple", "orange"] }}
        transition={{ duration: 4, repeat: Infinity }}
      />
    </motion.svg>
  );
}

export default AnimatedCircle;

Choosing the Right Method

The best method depends on your project's needs:

Method Best For Pros Cons
<img> Tag Static images, no dynamic styling Simple, familiar, performant for non-interactive images No dynamic styling, limited interactivity
Direct JSX (<svg>) Highly custom, dynamic, interactive, one-off SVGs Full control, dynamic styling via props, complex animations Can be verbose, less reusable, harder to maintain for many SVGs
SVG as React Component (SVGR) Reusable icons, icon libraries, dynamic styling Highly reusable, component-based, clean JSX, easy dynamic styling Requires build configuration (often handled by default)
SVG as Data URL Small, decorative SVGs, background images Reduces HTTP requests, embeddable in CSS Not easily modifiable, increased CSS/HTML size, harder to animate
react-svg (dynamic injection) External SVGs, post-load manipulation, advanced use Dynamic loading, robust DOM manipulation post-injection Adds dependency, more overhead for simple cases

Best Practices for Using SVGs in React

  • Optimize Your SVGs: Use tools like SVGOMG to remove unnecessary metadata, comments, and reduce file size.
  • Accessibility: Always include alt attributes for <img> tags and consider <title> and <desc> elements within inline SVGs for screen readers. Use aria-hidden="true" for purely decorative SVGs.
  • Semantic Naming: Use clear and descriptive class names or IDs for SVG elements when styling with CSS.
  • CSS vs. Inline Styles: Prefer CSS for static styling and global themes. Use inline styles or props for dynamic, component-specific changes.
  • Performance: For a large number of unique icons, consider creating an SVG sprite or using a font icon library for simple icons.
  • Avoid Over-Complexity: For very complex illustrations, a high-resolution raster image might sometimes be more performant than an incredibly large SVG file, though this is rare.

By leveraging these techniques and best practices, you can effectively integrate SVG images into your React applications, creating visually stunning and highly performant user interfaces.