avatarJennifer Fu

Summary

This context provides a guide on how to use SVG images in React applications, specifically within the Create React App environment.

Abstract

The context discusses the use of Scalable Vector Graphics (SVG) in React applications, focusing on the Create React App environment. It explains the benefits of SVG, such as its scalability and accessibility, and provides examples of how to use SVG in React. The guide covers various methods, including using SVG in JSX, as an image, as a React component, and as a background image. It also mentions the use of tools like SVGR to transform SVG into ready-to-use components. The context emphasizes the importance of SVG for building fast, performant, and accessible webpages.

Bullet points

  • SVG stands for Scalable Vector Graphics, which is a vector-based graphics format that can be searched, indexed, scripted, compressed, and built with accessibility.
  • Create React App comes with an SVG logo, which is defined in src/logo.svg.
  • SVG can be used in JSX directly, but this method violates separation of concerns.
  • Using SVG as an image is enabled by the built-in file-loader, which is configured by webpack.config.js.
  • SVG can also be placed in the public folder, but importing images is the recommended method.
  • Using SVG as a React component is enabled by the built-in SVGR, which transforms SVG into ready-to-use components.
  • Using SVG as a background image can be done by defining a selector in src/index.css.
  • SVG is powerful for building fast, performant, and accessible webpages.
  • There are a number of editors and VSCode extensions to help create complex SVGs.

Create React App and SVGs

A guide to show SVG images in React apps

Image courtesy of Wikipedia

SVG stands for Scalable Vector Graphics. It defines vector-based graphics in XML format. Compared to a raster-based bitmap (above left), the vector-based image (above right) preserves the shape while scaling up. In addition, as the nature of XML files, they can be searched, indexed, scripted, compressed, and built with accessibility. SVG is a widely used graphic format on the web.

SVG Logo in Create React App

Create React App comes with an SVG logo:

Image provided by the author.

This logo is defined in src/log.svg:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">      
  <g fill="#61DAFB">
    <path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
    <circle cx="420.9" cy="296.5" r="45.7"/>
    <path d="M520.5 78.1z"/>
  </g>
</svg>

At the root level, the svg tag defines an SVG document fragment, which has the name space http://www.w3.org/2000/svg and the rectangle viewBox starting from (0,0) point with width 841.9 and height 595.3.

The g tag groups elements together. It defines the fill color of the group. The first group are three overlapping ellipses, defined by the path tag. The d attribute is a set of commands which define the path. The commands have two formats:

  • The upper case commands are actions that use the absolute values.
  • The lower case commands are actions that use the relative values.
M/m = moveto
L/l = lineto
H/h = horizontal lineto
V/v = vertical lineto
C/c = curveto
S/s = smooth curveto
Q/q = quadratic Bézier curve
T/t = smooth quadratic Bézier curveto
A/a = elliptical Arc
Z/z = closepath

The second group defines the circle tag, which is centered at (420.9, 296.5) with the radius 45.7. The third group defines another path tag that does nothing.

It takes 2,671 bytes to define this logo. As pointed out in this issue, the logo SVG can be simplified to 428 bytes with the following definition:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
  <g fill="none" stroke="#61DAFB" stroke-width="23" >
    <ellipse cx="420.9" cy="296.5" rx="235" ry="91" />
    <ellipse cx="420.9" cy="296.5" rx="235" ry="91" transform="rotate(120 420.9 296.5)"/>
    <ellipse cx="420.9" cy="296.5" rx="235" ry="91" transform="rotate(240 420.9 296.5)"/>
  </g>
  <circle cx="420.9" cy="296.5" r="45.7" fill="#61DAFB"/>
</svg>

It is a group of three ellipses without filling. The three ellipses have the same center, x-axis radius, and y-axis radius. The second ellipse rotates 120-degree with the center (420.9, 296.5). The third ellipse rotates 240-degree with the center, (420.9, 296.5). The circle is defined outside the group, with the fill color and the default stroke-width set to 1.

How to Use SVG in React?

Create React App brings convenience for SVG. You do not need to think about how to configure webpack settings. It has been set up already. There are a number of ways to use SVG in Create React App. We are going to describe them one by one.

Use SVG in JSX

SVG can be used in JSX directly.

Lines 5-7 define an SVG, which prints out a text: Today is Sunday. Mixing SVG code inside JSX violates separation of concerns, a design principle for separating a computer program into distinct sections for separate concerns. It works, but it is not a recommended method.

Use SVG as an Image

Using the img tag is how Create React App embeds the logo SVG, which is defined in a separate file, src/logo.svg.

This method is enabled by the built-in file-loader, which is configured by webpack.config.js:

Put our text SVG into src/logo.svg:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 100">
  <text x="10" y="20">Today is Sunday</text>
</svg>

Then it can be invoked as an image in JSX:

In line 2, the import statement tells webpack to use this image.

At line 7, the SVG file is used as a normal image via the img tag, where src specifies a url as the path to the image. The configured file-loader resolves import of ./logo.svg into a URL and emits the file into the output directory. The final filename will be generated by webpack from its content hash. In this way, a browser will not use a cached image if image content changes.

logo.svg can also be placed in the public folder. Then it does not need to be imported. It can be directly used by line 5 in the following way:

Both ways work, but importing images is the recommended method. In rare cases, images are put into the public folder:

  • Specific file names are needed in the build output.
  • There are thousands of images, and they need to be dynamically referenced by the paths.

Use SVG as a React Component

This way is enabled by the built-in svgr, which transforms SVG into ready to use components.

Let’s run SVGR CLI command for src/logo.svg:

$ npx @svgr/cli --icon --replace-attr-values "#063855=currentColor" src/logo.svg
npx: installed 161 in 26.523s
import * as React from "react";
function SvgLogo(props) {
  return (
    <svg viewBox="0 0 300 100" width="1em" height="1em" {...props}>
      <text x={10} y={20}>
        {"Today is Sunday"}
      </text>
    </svg>
  );
}
export default SvgLogo;

It generates a React component, named SvgLogo. The webpack plugin does this transformation for us.

This transformation names the generate component ReactComponent, which will be unique for each import.

In line 2, ReactComponent is renamed as Logo, which is used as a React component in line 6.

Using SVG as a React Component has significant advantages. ReactComponent accepts props that allow us to configure the SVG component. It also allows a title for accessibility.

In the above code, Logo has been added three times. Each time (line 7, 8, and 9), the component has its own title, color, and transformation.

Instead of the boring text Today is Sunday, we see the following colorful transformed texts:

Isn’t that cool?

Use SVG as a Background Image

For the previous example of colorful transformed texts, we can also add an SVG file as background.

We define src/index.css to include the following selector:

div {
  background: url(background.svg)
}

The background gradient color is defined in src/background.svg:

<svg xmlns="http://www.w3.org/2000/svg">
  <title>Background gradient</title>
  <defs>
    <linearGradient id="g" x1="0%" x2="100%" y1="0%" y2="100%">
      <stop style="stop-color: green;" offset="0"/>
      <stop style="stop-color: yellow;" offset="1"/
    </linearGradient>
  </defs>
  <rect style="fill: url(#g);" width="100%" height="100%"/>
</svg>

It is a good practice to have a title for SVG. This linear gradient color is composed of green and yellow.

Our colorful transformed texts become more colorful.

Conclusion

SVG is powerful for building fast, performant, and accessible webpages. You may wonder how to create a complicated SVG. There are a number of editors to help us. VSCode provides quite a few extensions too. Vectr is a free online editor.

This is a drawing that we made for fun. It looks pretty to be put it into src/logo.svg with the gradient background.

The generated SVG file is a bit long. If you are interested, open the following image to check out the 256 lines of code in the Github gist.

Happy SVGing! Thanks for reading. I hope this was helpful.

You can see my other Medium publications here.

Programming
SVG
React
UX
JavaScript
Recommended from ReadMedium