DEV Community

loading...
Cover image for A better way to use SVGs

A better way to use SVGs

shubhamjain profile image Shubham Jain ・2 min read

It's 2021, and we are still not settled on the best way to SVGs. Inline SVGs offer all the benefits—being able to directly modify fill color, use CSS variables, and modify the inner SVG elements—but have the obvious downside that they make the code messy.

Storing them externally is a better option, but the only reliable way to use them is the <img> tag, which comes with severe limitations.

<!-- Can't modify the fill color if you want -->
<img src="/path/to/img.svg" />
Enter fullscreen mode Exit fullscreen mode

To solve this, I have created a library that offers all the benefits of inline SVGs, while still storing them externally. It's called svg-loader.

Check, for example, this logo of my project in SVG.

<img src="https://s2.svgbox.net/assets/logo-white.svg" />
Enter fullscreen mode Exit fullscreen mode

Preview

Since the fill color is not defined, it will default to black and there's not much you can do about changing that. There are a few hacks around this using the filter property, but they are complex and not easy to modify.

In comes, svg-loader. You just have to drop the script in and the external SVGs will be fetched and injected inside the element. Like, this:

<script type="text/javascript" src="https://unpkg.com/external-svg-loader@1.0.0/svg-loader.min.js" async></script>

<div style="display:flex;">
    <div style="background:black;">
        <svg data-src="https://s2.svgbox.net/assets/logo-white.svg" fill="yellow"></svg>
    </div>
    <div style="background:purple;">
        <svg data-src="https://s2.svgbox.net/assets/logo-white.svg" fill="white"></svg>
    </div>
    <div style="background:green;">
        <svg data-src="https://s2.svgbox.net/assets/logo-white.svg" fill="white"></svg>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Preview

Alt Text

View on JS Fiddle

The library is very light <2KB (post-compression). The loads are lightning fast and also comes with a way to cache the file for longer. So, the image isn't fetched repeatedly. And pretty much works anywhere.

Compatible with React, Vue, Angular

svg-loader is framework agnostic and works with most front-end frameworks. You just need to include the library somewhere and everything else will be handled:

import React from 'react'
import ReactDOM from 'react-dom'

import 'external-svg-loader';

class App extends React.Component {
  render () {
    return (
      <svg
        data-src="https://s2.svgbox.net/materialui.svg?ic=mail"
        fill="currentColor"
        width="50px"
        height="50px"
        style={{
          color: 'red'
        }}
      />
    )
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('container')
);
Enter fullscreen mode Exit fullscreen mode

View on Codesandbox

Note: The resources need to be compatible with the CORS policy since XHR is used to fetch them.

Thoughts? Questions? Feel free to reply here.

Discussion (11)

pic
Editor guide
Collapse
darkwiiplayer profile image
DarkWiiPlayer • Edited

Or, you know, just use <object>, which works great too :D

(or <use> inside an <svg> tag)

Collapse
jannikbuscha profile image
Jannik Buscha

can you provide a vue example? i tried the code but i got a IntersectionObserver is not defined error.

Collapse
shubhamjain profile image
Shubham Jain Author

Happy to help! Can you please share the code somewhere (Github, gist, JSFiddle)?

Collapse
jannikbuscha profile image
Thread Thread
shubhamjain profile image
Shubham Jain Author

It seems in nuxt.js using external library (like even jQuery) takes some effort. THe easiest way I found was to include it in the head tag (kaloraat.com/articles/how-to-use-j...)

Here's the edited version: codesandbox.io/s/kind-johnson-1dfi...

Collapse
matjones profile image
Collapse
shubhamjain profile image
Shubham Jain Author

Not the same thing. That's a code generator, and while it solves a few problems. I think creating components out of tiny SVG icons is not the best solution to deal with this.

Collapse
said_mounaim profile image
Said Mounaim

Niice ! Thank you

Collapse
ms_yogii profile image
Yogini Bende

I am facing issues of svg looking little blurry on safari on mobile. Hopefully this will solve that issue.

Collapse
idodav profile image
Ido David

Great library!

Collapse
mahmoudalfall profile image
mahmoud-alfall

can i use your library to modify svg gradient's stop points.
btw i don't know very much about svg coding