Using React with SVG images

Perhaps the biggest selling point for Facebook's UI library, React is reusability. Build a component once, and you can import it in multiple places across your project, or distribute it for the community's benefit.

Reusability makes React an excellent library for creating HTML components. But what if we used React to create SVG components?

I used this technique to build the Search box component for Vets.gov. Turning the magnifying glass icon into a React component made sense; it's used twice just for the Search box. And by using SVG inline, we can use CSS to change the color of the icon instead of using multiple icon files.

Vets.gov search component.

Figure 1: The Vets.gov Search component.

Things to consider

When creating the IconSearch and IconHelp components, I considered how they might be used throughout the site.

  • Would it always be the same color? (No.)
  • Could they ever become the child of a clickable element, such as a, button, or label? (Yes. Always.)
  • Might it ever be used as a visual replacement for text? (Yes.)

The answers to those questions determined which elements and attributes would become props and which could remain as markup, as shown below.

class IconSearch extends React.Component {
  render() {
    let svgTitle;

    if (this.props.title) {
      svgTitle = <title>{this.props.title}</title>;
    }

    return (
      <svg width="24" height="24" viewBox="0 0 216 146"
          pointerEvents="none"
          className={this.props.cssClass}
          id={this.props.id}>
        {svgTitle}
        <path fill={this.props.color}
          d="M172.77 123.025L144.825 95.08c6.735-9.722z..."/>
      </svg>
    );
  }
}

In this case:

  • Defining fill and cssClass properties (props) means the icon can be displayed in any color.
  • Adding a pointerEvents attribute prevents the icon from receiving mouse events.
  • Defining a title property lets us include descriptive text for AT users when necessary, and eliminate it when it's redundant.

Prepare your SVG for React and JSX

Now you can't just copy-and-paste an SVG document into a React/JSX file and have it work. JSX looks like XML, but it isn't XML. We'll need to make our SVG document conform to JSX rules by taking the following steps.

  • Remove the <? xml ?> prolog.
  • Remove <!-- comments -->.
  • Remove the xmlns:xlink attribute from the opening <svg> tag.
  • Change hyphenated SVG attributes to be camelCase instead. For example, stroke-width should become strokeWidth and fill-rule needs to be fillRule.
  • Use /> instead of closing tags, e.g. <rect /> not <rect></rect>

If you forget to do any of these things, don't worry. React will log an error message to the console (you're using the React Developer Tools Extension, yes?).

If that's too much work for you, you can also use svgr, a Node-based tool that converts SVG files to React components.

These are really simple examples of course. SVG React components are only limited by the features of SVG. A more complex component might use React to create a reusable SVG graph, pie chart or map.

Subscribe to the Webinista (Not) Weekly

A mix of tech, business, culture, and a smidge of humble bragging. I send it sporadically, but no more than twice per month.

View old newsletters