Using SVG in React
Tags: react, webdev, beginners, tutorial
Published: 2024-01-08 09:11:36

<a href="https://github.com/refinedev/refine">
   <img src="https://refine.ams3.cdn.digitaloceanspaces.com/blog-banners/retool-alternative.png" alt="refine repo" /> 

</a>

---


## Introduction

In the world of making websites look good, pictures, especially images, are super important. They make up a big part (60%!) of what you see online, making websites more interesting and helping to share information. Among the many tools that developers use, React SVG stands out. It's like a superhero for putting cool and scalable graphics, especially Scalable Vector Graphics (SVG), into websites.

When developers want to make websites that look awesome and do cool things, they need graphics that can change and fit well. React SVG, which is like a special tool in the React world, helps developers use Scalable Vector Graphics (SVG) really easily.

So, in this article, we'll talk about React SVG and how it makes the process of adding and handling images on modern websites more versatile and fun.




## What is SVG?

The content or code of an SVG file is an HTML code, just like other image files like JPG, PNG, GIFS, etc have their encodings and format respectively. The whole code of an SVG is wrapped in a single `svg` element. The content or code of the SVG are wide array of elements that are dedicated to the construction, drawing, and layout of vector images and diagrams.

```tsx
<svg>...</svg>
```

We have seen that SVGs are HTML code, so they can be rendered on the browser. Now, they can be manipulated with CSS and JavaScript. We can get the instance of an `svg` using the DOM APIs like `document.querySelector`, and manipulate it with JavaScript. We can also style it with CSS.

The instance of an `svg` is also available in the DOM, it is the `HTMLSVGElement`. This is to further show you that the browser recognizes the `svg` as an HTML element.

```tsx
const svg = document.querySelector("svg");
console.log(svg instanceof HTMLSVGElement); // true
```

So basically, SVG images are HTML. So they can be rendered on the browser. Now, SVG array of elements can only be rendered inside the `svg` block, they can be rendered outside it but the browser will see it as a custom element. So it only has meaning within the `svg` code. The use of SVG is quite versatile. SVGs can be used to:

- draw text effects
- animations. Most animations on the browser are done with the use of SVG.
- draw data visualization e.g. charts, and bars. Chartsjs uses SVG to draw charts.
- render a UI design field. Figma uses SVG to render all those designs we do on it, and all those drag and drop are SVG designs.
- 3D graphics. This library called threejs uses SVG to render 3D graphics on the browser.
- act as a stand-in image or placeholder for lazily-loaded images. This is because SVGs are very small in size and can be rendered on the browser very fast.

## Importing SVGs

In a React project, there are several approaches to importing SVG files, each with its advantages and use cases. Here are a few common methods.

## Importing as a React Component:

In this approach, you can import SVG files directly as React components. SVG files have a `.svg` extension, so you can import them like any other JavaScript file. This method allows you to treat SVGs as React components, making them easy to manipulate and style using React's capabilities.

Let's say we have this svg code that we want to use in our React application:

```tsx
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="40" stroke="black" strokeWidth="3" fill="red" />
</svg>
```

Now, we want to use this as a file in our React application. We can do this by creating a file called `MySvg.svg` and pasting the code above in it.

```tsx 
// title="src/icons/circle.svg"

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="40" stroke="black" strokeWidth="3" fill="red" />
</svg>
```

Then we can import it into our React application like this:

```tsx
import { ReactComponent as CircleSvg } from "./icons/circle.svg";

// Usage in JSX
const MyComponent = () => {
  return <CircleSvg />;
};
```

Here, `CircleSvg` is a special import syntax that comes with `Create React App` and Webpack. It allows you to import SVG files as React components. Once, we import it, we can use it as a React component in our JSX. The code inside the SVG file is not a React component at all but once we import it using the `import` it is automatically converted to a React component.

## Using an `<img>` Tag

We can also use the traditional HTML `<img>` tag to display SVGs. This approach is straightforward and suitable for simple use cases.

```tsx
import CircleSvg from "./icons/circle.svg";

// Usage in JSX
const MyComponent = () => {
  return <img src={CircleSvg} alt="My SVG" />;
};
```

Here we are importing the SVG file and using it as the `src` attribute of the `<img>` tag.

The above will be converted to this:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yppm837bdqmptpc1c5yj.png)


The cons of this approach is that the styling and manipulating of the SVG might be limited. For example, we cannot be able to change the color of the SVG using CSS. We can only change the color of the SVG using the `fill` attribute of the `<img>` tag.

```tsx
import CircleSvg from "./icons/circle.svg";

// Usage in JSX
const MyComponent = () => {
  return <img src={CircleSvg} alt="My SVG" fill="red" />;
};
```

Here, we are using the `fill` attribute of the `<img>` tag to change the color of the SVG. This is the only way we can change the color of the SVG using the `<img>` tag. We cannot use CSS to change the color of the SVG.

## Inline SVG

Inline SVG involves directly embedding the SVG markup within your React component. This approach provides more control over styling and manipulation directly within the component.

```tsx
import React from "react";

// Usage in JSX
const MyComponent = () => {
  return (
    <div>
      <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
        <circle cx="50" cy="50" r="40" stroke="black" strokeWidth="3" fill="red" />
      </svg>
    </div>
  );
};
```

Here, we are directly embedding the SVG code in our React component. We just copied the contents of the SVG file and pasted it into our React component. It renders as an HTML element directly. Here, we have total control over the SVG. We can manipulate it with CSS and JavaScript. We can also use React to manipulate it.

This method is suitable for smaller, inline SVGs, and it gives you direct control over each element. The cons are that the svg code might be large and we will end up with a bloated component file size. Also, the svg becomes hard to maintain, we can mitigate against this if we use the `react-svg` library.

## Using `react-svg`

The `[react-svg](https://www.npmjs.com/package/react-svg)` library gives us the ability to embed inline SVGs while still able to manipulate the inline SVGs.

```
npm install react-svg
```

The `react-svg` exports a `ReactSVG` component. The component has a props `src` that receives the inline SVG.

```tsx
import { ReactSVG } from "react-svg";

<ReactSVG src="circle.svg" />;
```

Here, import the `ReactSVG` component and pass the URL of the `circle.svg` file to the `src` props. There are many useful props that we can pass to the `ReactSVG`. We can request the component to cache the SVGs, we can attach a click handler to the SVG, and many [more](https://www.npmjs.com/package/react-svg)



There are specific loaders like `react-svg-loader` or `svg-react-loader` that allow you to import SVG files directly and use them as React components.

```tsx
import CircleSvg from "svg-react-loader!./icons/circle.svg";

// Usage in JSX
const MyComponent = () => {
  return <CircleSvg />;
};
```

Ensure you have these loaders installed (`npm install --save-dev react-svg-loader` or `npm install --save-dev svg-react-loader`) and configured in your build setup.

Choose the method that best suits your project requirements and workflow. Each approach has its strengths, and the choice often depends on factors such as ease of use, scalability, and the specific needs of your application.

## Styling SVGs in React

We have seen ways to import and use SVGs in React. Now, let's look at ways we can style SVGs in React.

Using SVGs in React components is common for adding scalable graphics. There are multiple methods to style SVGs to make them fit in with the rest of your UI. Here’s a rundown of the options you have for styling SVGs in React:

### Inline Styles

You can dynamically change the style of SVG elements by passing a style object directly to the SVG component.

```
const MySvgComponent = () => (
    <svg style={{ fill: "blue", width: "50px", height: "50px" }}>
      {/* paths, circles, etc. */}
    </svg>
);
```

### CSS Stylesheets

Just like HTML elements, you can style SVGs using CSS classes or IDs.

```tsx
// styles.css
.my-svg {
  fill: blue;
  width: 50px;
  height: 50px;
}

import "./styles.css";

const MySvgComponent = () => (
  <svg className="my-svg">{/* paths, circles, etc. */}</svg>
);
```

### CSS Modules (Scoped Styles)

If you're using CSS Modules, you can import styles from a `.module.css` file which will automatically scope the class names to avoid conflicts.

```tsx title="MySvgComponent.module.css"
.mySvg {
  fill: blue;
  width: 50px;
  height: 50px;
}

import styles from "./MySvgComponent.module.css";

const MySvgComponent = () => (
  <svg className={styles.mySvg}>{/* paths, circles, etc. */}</svg>
);
```

### Styled Components (CSS-in-JS)

This is a popular CSS-in-JS library that lets you use component-level styles.

```tsx
import styled from "styled-components";

const StyledSvg = styled.svg`
  fill: blue;
  width: 50px;
  height: 50px;
`;

const MySvgComponent = () => <StyledSvg>{/_ paths, circles, etc. _/}</StyledSvg>;
```

### Emotion (CSS-in-JS) Another `CSS-in-JS` library that has similar functionality to Styled Components.

```tsx
/\*_ @jsxImportSource @emotion/react _/
import { css } from '@emotion/react';

const style = css`  fill: blue;
  width: 50px;
  height: 50px;`;

const MySvgComponent = () => (
<svg css={style}>
{/* paths, circles, etc. */}
</svg>
);
```

### Inline SVG as JSX

If you import your SVG as a React component (using a loader like `@svgr/webpack`), you can directly apply styles to its JSX.

```tsx
import { ReactComponent as MySvg } from "./mySvg.svg";

const MySvgComponent = () => <MySvg style={{ fill: "blue", width: "50px", height: "50px" }} />;
```

### Manipulating SVG Props

SVG elements have specific properties (such as fill, stroke, width, height, etc.) that can be manipulated in JSX:

```tsx
const MySvgComponent = ({ color }) => (
  <svg width="50" height="50">
    <circle cx="25" cy="25" r="20" fill={color} />
  </svg>
);
```

Each of these methods has its use cases. Inline styles and manipulating SVG props are great for quick dynamic styling changes, while CSS stylesheets, CSS Modules, and CSS-in-JS libraries offer more power and flexibility, especially when you have complex styles or you want to keep your styles organized and modular.

### Dynamic SVGs

Dynamic SVGs in React can provide a rich and interactive experience for users. SVG (Scalable Vector Graphics) is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation. When using React, you can create interactive SVG elements that respond to user input, changes in state, or props. Here's a conceptual guide on how to do this:

### Initializing State and Props

Start by deciding what aspects of your SVG need to be dynamic. For instance, you might want to dynamically change the color, size, or position of an SVG element. You can use the useState hook to manage stateful values within your components, and you can pass down props to configure components from a parent.

```tsx
const [color, setColor] = useState("blue");
```

### Creating SVG Components

You can create a React component that returns SVG elements. These components can then take props or use state to determine how the SVG is rendered.

```tsx
const MyCircle = ({ color }) => (
  <svg width="100" height="100">
    <circle cx="50" cy="50" r="40" stroke="black" strokeWidth="3" fill={color} />
  </svg>
);
```

### Adding Interactivity

Attach event handlers such as `onClick`, `onMouseOver`, `onMouseOut`, etc., to SVG elements to make them interactive.

```tsx
const InteractiveCircle = () => {
  const [color, setColor] = useState("blue");

  const changeColor = (newColor) => setColor(newColor);

  return (
    <svg width="100" height="100">
      <circle
        cx="50"
        cy="50"
        r="40"
        stroke="black"
        strokeWidth="3"
        fill={color}
        onMouseOver={() => changeColor("green")}
        onMouseOut={() => changeColor("blue")}
      />
    </svg>
  );
};
```

### Animating SVG Elements

You could use CSS animations or the Web Animations API to animate SVG elements. React's useEffect hook can be used to trigger animations when certain states or props change.

```tsx
useEffect(() => {
  // Trigger animation logic when 'color' changes
}, [color]);
```

### Composing SVG Components

Larger SVG graphics can be composed of smaller SVG components, allowing you to reuse logic and simplify your codebase.

```tsx
const App = () => (
  <svg width="200" height="200">
    <MyCircle color="blue" />
    <MyCircle color="red" />
  </svg>
);
```

### Using Third-Party Libraries

There are several libraries available that make working with SVGs in React easier. For instance, `d3-react-svg`, combines the power of D3.js with React to create data visualizations.

### Animation with SVGs in React

Animating SVGs in React can greatly enhance the user experience by providing a visually appealing way to convey changes or draw attention to certain parts of the UI. Let's look at some steps and some considerations for implementing SVG animations in React:

### Create or Import an SVG

You can create SVGs using graphic design software or write the SVG markup directly. SVGs can then be imported into a React component either as a React component using JSX or as a file if you're using tools like Create React App which supports SVG imports.

Example SVG as JSX in a React component:

```tsx
const MySVG = () => (
  <svg width="100" height="100">
    <circle cx="50" cy="50" r="40" stroke="green" strokeWidth="4" fill="yellow" />
  </svg>
);
```

Importing SVG as a module:

```tsx
import { ReactComponent as MySVG } from "./my-svg.svg";

const MyComponent = () => (
  <div>
    <MySVG />
  </div>
);
```

### Basic CSS Animations

For simple animations, you might not need any additional libraries. CSS can be used to animate SVG properties such as opacity, transform, or stroke-related properties.

Example using CSS:

```tsx
    @keyframes fadeIn {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }

    .my-svg {
      animation: fadeIn 2s ease-in-out infinite;
    }
    const MySVG = () => (
      <svg className="my-svg" width="100" height="100">
        <circle
          cx="50"
          cy="50"
          r="40"
          stroke="green"
          strokeWidth="4"
          fill="yellow"
        />
      </svg>
    );
```

### Animation Libraries

For more complex or interactive animations, you might want to use a library like [`react-spring`] ([https://www.react-spring.dev/docs/getting-started](https://www.react-spring.dev/docs/getting-started)). React Spring is a library for building interactive, data-driven, and animated UI components. It can animate HTML, SVG, Native Elements, Three.js, and more.

To use `react-spring`, you need to install it:

```
npm install react-spring
```

Example with `react-spring`:

```tsx
import { useSpring, animated } from "react-spring";

const AnimatedSVG = () => {
  const props = useSpring({
    from: { opacity: 0 },
    to: { opacity: 1 },
    config: { duration: 1000 },
  });

  return (
    <animated.svg style={props} width="100" height="100">
      <circle cx="50" cy="50" r="40" stroke="green" strokeWidth="4" fill="yellow" />
    </animated.svg>
  );
};
```

### Interactivity

You can combine `react-spring` with React's event handlers to create interactive animations. For example, you might want an SVG to animate when a user hovers over it or clicks on it.

```tsx
import { useSpring, animated } from "react-spring";

const InteractiveSVG = () => {
  const [animatedProps, set] = useSpring(() => ({
    to: { opacity: 1, transform: "scale(1)" },
    from: { opacity: 0.5, transform: "scale(0.5)" },
  }));

  return (
    <animated.svg
      onMouseEnter={() => set({ opacity: 1, transformText: "scale(1.2)" })}
      onMouseLeave={() => set({ opacity: 1, transform: "scale(1)" })}
      style={animatedProps}
      width="100"
      height="100"
    >
      <circle cx="50" cy="50" r="40" stroke="green" strokeWidth="4" fill="yellow" />
    </animated.svg>
  );
};

export default InteractiveSVG;
```