Using SVG in React

Necati Özmen - Jan 8 - - Dev Community


refine repo


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.

<svg>...</svg>
Enter fullscreen mode Exit fullscreen mode

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.

const svg = document.querySelector("svg");
console.log(svg instanceof HTMLSVGElement); // true
Enter fullscreen mode Exit fullscreen mode

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:

<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>
Enter fullscreen mode Exit fullscreen mode

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.

// 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>
Enter fullscreen mode Exit fullscreen mode

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

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

// Usage in JSX
const MyComponent = () => {
  return <CircleSvg />;
};
Enter fullscreen mode Exit fullscreen mode

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.

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

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

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

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.

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

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

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.

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>
  );
};
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

import { ReactSVG } from "react-svg";

<ReactSVG src="circle.svg" />;
Enter fullscreen mode Exit fullscreen mode

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

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.

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

// Usage in JSX
const MyComponent = () => {
  return <CircleSvg />;
};
Enter fullscreen mode Exit fullscreen mode

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>
);
Enter fullscreen mode Exit fullscreen mode

CSS Stylesheets

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

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

import "./styles.css";

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

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 = () => (
{/* paths, circles, etc. */}
);




### 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>;
Enter fullscreen mode Exit fullscreen mode

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

/\*_ @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>
);
Enter fullscreen mode Exit fullscreen mode

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.

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

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

Manipulating SVG Props

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

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

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.

const [color, setColor] = useState("blue");
Enter fullscreen mode Exit fullscreen mode

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.

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

Adding Interactivity

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

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>
  );
};
Enter fullscreen mode Exit fullscreen mode

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.

useEffect(() => {
  // Trigger animation logic when 'color' changes
}, [color]);
Enter fullscreen mode Exit fullscreen mode

Composing SVG Components

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

const App = () => (
  <svg width="200" height="200">
    <MyCircle color="blue" />
    <MyCircle color="red" />
  </svg>
);
Enter fullscreen mode Exit fullscreen mode

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:

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

Importing SVG as a module:

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

const MyComponent = () => (
  <div>
    <MySVG />
  </div>
);
Enter fullscreen mode Exit fullscreen mode

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:

    @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>
    );
Enter fullscreen mode Exit fullscreen mode

Animation Libraries

For more complex or interactive animations, you might want to use a library like react-spring. 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
Enter fullscreen mode Exit fullscreen mode

Example with react-spring:

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>
  );
};
Enter fullscreen mode Exit fullscreen mode

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.

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;
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .