This isn’t a new problem: the dilemma of getting SVGs to correctly render with React, but it is a problem that I hadn’t had to deal with and overcome until recently, and I’d like to share my experiences in the hope that it saves someone else a few hours of searching Github, StackOverflow and NPM.

At my current company, I’ve worked for two separate development teams, both of whom use JavaScript microservices for their UIs — one uses AngularJS, the other uses JavaScript MVC. All the backend services are Java Spring Boot applications.

When the news broke a while back that Google was going to stop supporting AngularJS 1.5 (the version we’re using), it became clear we could either:

upgrade the system to AngularJS 1.7 (which will continue to have long term support for 3 more years), upgrade our application to Angular 2, or migrate to ReactJS.

One of my colleagues and I were tasked with figuring out which was the best direction to take. This exploration was a process which deserves its own blog post, but suffice it to say, I was most in favor of venturing into React, and after we’d looked at our options and tinkered, we decided to see if we could make a small proof-of-concept using React work.

About 4 hours after starting our React POC, we had a working, albeit, not very pretty, app. We added Jest and Enzyme unit tests, Cypress end-to-end tests and more. But for almost two weeks one thing eluded us: getting an SVG graphic to render correctly in the DOM.

Why SVGs? What’s the Benefit? Why Not Just Make It Into a PNG?

Great question. The benefits of using SVGs are many, and in case you don’t know, SVG stands for Scalable Vector Graphics. While the textbook definition sounds dense:

“S VG is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation” — Wikipedia, Scalable Vector Graphics

they basically take the place of traditional images in other formats like JPEG, PNG, TIFF or GIF.

Here are a few reasons why SVGs are superior to the other image formats:

Crystal clear resolution no matter the screen size, zoom level or image size — since SVGs are built on vector paths, shapes and fills, they can scale to any size with no loss of clarity. PNGs, on the other hand, are based on pixels, which won’t look sharp and clear at all times (especially on retina display devices).

— since SVGs are built on vector paths, shapes and fills, they can scale to any size with no loss of clarity. PNGs, on the other hand, are based on pixels, which won’t look sharp and clear at all times (especially on retina display devices). Load speed is much faster — if you’re using high res images on your site to cater to those retina displays, the PNG files can be pretty sizable, and larger files render more slowly (duh). SVGs are just code, which means smaller file sizes (unless you’re loading something very detailed with a million vector paths).

— if you’re using high res images on your site to cater to those retina displays, the PNG files can be pretty sizable, and larger files render more slowly (duh). SVGs are just code, which means smaller file sizes (unless you’re loading something very detailed with a million vector paths). Animation is possible — unlike PNG files which are static — what you see is what you get, SVGs can be animated and styled with CSS. Animations, different colors, changes to state (like hover or click), all these things can be done to SVGs.

— unlike PNG files which are static — what you see is what you get, SVGs can be animated and styled with CSS. Animations, different colors, changes to state (like hover or click), all these things can be done to SVGs. Accessibility and SEO — Google indexes SVGs, which means better SEO scores for your site and better accessibility for people with vision impairments visiting your site.

Right, So SVGs It Is, Now How to Use Them In React

For my project, I was seeing if I could recreate one of the simpler screens of the existing AngularJS application in React. This screen contained four big, clickable cards that would take users to other various screens, and each card had a nice SVG file associated with the words.

So I copied the SVG files from the original project, moved them into React, imported the files into the component that would render them, added

<Image source={require(‘../img/key.svg’)} />

in the JSX, added the CSS styling, waited for Webpack to do its magical parsing and…nothing. Well, not quite nothing, errors in the console about unrecognized file types, but certainly no key icon displayed in the UI.

And thus began the search for the library I needed to render SVGs correctly in React. This was a days long process. If you’re unaware there’s approximately 7,845,923 NPM modules that all claim to make React play nicely with SVGs. Some of them probably work, the first 10 or so I tried, did not.

Then… SVG Inline Loader

Then, I found it. An NPM module aptly named svg-inline-loader, it had decent documentation, it had 3,200 weekly downloads, it had 325 stars on Github, it was developed and maintained by the core team that built Webpack, it seemed promising.

So I gave it a shot and saved it to my dev dependencies in the package.json file.

npm install svg-inline-loader react-inlinesvg --save-dev

Then, added the configuration object to the webpack.config.js file:

{

test: /\.svg$/,

loader: 'svg-inline-loader'

}

And I was good to go. One simple update to Webpack, a small adjustment to the JSX syntax and…

import React, { Component } from 'react';

import KeyImage from '../img/key.svg';

import SVG from 'react-inlinesvg'; class Card extends Component(){

return(

<div>

< /* other UI stuff here */ >

<SVG src={KeyImage} />

</div>

)

}

BOOM — SVG displayed!

I’d also like to add that this NPM module has some pretty nifty extra features: it can remove extra tag info from SVGs (which happens a lot when they’re generated with Sketch or Adobe), and it can add classes or IDs to prevent SVG collisions. Nice.

And that was it. No CSS changes, no super weird syntaxes, nothing like that. Just svg-inline-loader, an extra module loader for Webpack, and the problem was solved.

Thanks for reading, I hope it helps and claps are very much appreciated!

If you enjoyed reading this, you may also enjoy some of my other blogs: