Using SVG Icons in React

SVG is a two-dimensional vector graphic format that allows scaling images on the web without losing quality. Unlike traditional image formats such as JPG or PNG, SVGs allow you to change their colors and dimensions directly in the code, without needing a graphical editor of any sort.

This article describes a simple way to transform plain old SVG code into clean and intuitive React code. In other words, it will illustrate how to make the transition...

From this :

<svg
  width="32"
  height="32"
  viewBox="0 0 16 16"
  fill="none"
  xmlns="http://www.w3.org/2000/svg"
>
  <circle cx="6.5" cy="6.5" r="5.75" stroke="#000000" stroke-width="1.5" />
  <path
    d="M11 11L15 15"
    stroke="#000000"
    stroke-width="1.5"
    stroke-linecap="round"
  />
</svg>

To this :

<SVGIcon name="search" width={32} color="#23fec6" />

... without using any additional npm packages or modifying your app's webpack config.

Anatomy of SVG

Before creating the Icon Component, let's cover the very basics of an SVG element.

  • ViewBox - The viewBox attribute defines the aspect ratio of the image. It also defines how the coordinates used inside the SVG should be scaled to fit the total space available.

  • Width, Height - These attributes define the width and height in pixels or percentage of the SVG's parent container width or height. If these attributes are removed, or set to 100%, the SVG becomes fluid, i.e. it scales to the size of its parent container.

  • Path, Circle, Rect - These basic elements are the building blocks of an SVG. Most SVG Icons would not make use of any other elements. What's important to know about these elements is that they all take Stroke and Fill attributes that define their color.

React Icon Component

Now that we're familiar with the anatomy of an SVG, let's examine the following React code.

export const SVGIcon = ({
  name = "default",
  width = "100%",
  height = "100%",
  color = "#000",
}) => {
  return (
    <svg
      viewBox={ICONS[name].viewBox}
      width={width}
      height={height}
      className={`icon-${name}`}
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      {ICONS[name].paths(color)}
    </svg>
  );
};

The SVGIcon component serves as a wrapper for all our icons, allowing to use SVG code that repeats in one single place, while retrieving icon-specific code (viewBox and paths) from an object called ICONS.

const ICONS = {
  default: {
    viewBox: "0 0 16 16",
    paths: color => <path d="" />,
  },
  search: {
    viewBox: "0 0 32 32",
    paths: color => (
      <>
        <circle cx="6.5" cy="6.5" r="5.75" stroke={color} strokeWidth="1.5" />
        <path
          d="M11 11L15 15"
          stroke={color}
          strokeWidth="1.5"
          strokeLinecap="round"
        />
      </>
    ),
  },
  // etc ...
};

Styling with CSS

Apart from being able to set the color of an icon using the color prop, one can also do this via CSS. This is especially useful when we need to add a hover effect to an icon.

Our SVGIcon component allows to select a specific icon by class name, and then apply CSS to the desired inner element - in this case that's the path:

.icon-search:hover path {
  stroke: #0052e0;
}

Final Result

Feel free to check the full code and a few icon examples below: