SVG is an image format that is especially well suited to JavaScript. SVG stands for "scalable vector graphics", which you can grow or shrink an SVG image to any arbitrary size without loosing quality. What makes SVGs so special for JavaScript is that SVGs are defined in an XML format that's very similar to HTML, so much so that you can define SVGs inline in HTML files and manipulate them using JavaScript frameworks.

Basic SVG in HTML

Below is an SVG version of the yin and yang symbol from Wikimedia commons.

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="-40 -40 80 80">
  <circle r="39"/>
  <path d="M0,38a38,38 0 0 1 0,-76a19,19 0 0 1 0,38a19,19 0 0 0 0,38" fill="#fff"/>
  <circle cy="19" r="5" fill="#fff"/>
  <circle cy="-19" r="5"/>
</svg>

Here's what it looks like in the browser.


An SVG image is just a collection of shapes defined in XML, like circles, rectangles, or arbitrary paths. You can modify an SVG using a plain old text editor like VS Code, or an online viewer. There is also an atom plugin that previews SVGs. For example, if you comment out the last circle tag from the above image, you remove the top black dot.

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="-40 -40 80 80">
  <circle r="39"/>
  <path d="M0,38a38,38 0 0 1 0,-76a19,19 0 0 1 0,38a19,19 0 0 0 0,38" fill="#fff"/>
  <circle cy="19" r="5" fill="#fff"/>
  <!-- <circle cy="-19" r="5"/> -->
</svg>

SVGs support comments. There is an extremely popular npm module for optimizing SVGs called svgo that minifies SVGs by removing comments and other non-functional elements.

Scaling an SVG is as easy as increasing the width and height properties of the svg tag. No need to modify any of the SVG internals. Below is how you double the height and width of the yin yang symbol to 400x400.

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="-40 -40 80 80">...</svg>

SVG With Vue

Because you can embed SVGs into the browser, you can also create and manipulate SVGs using component-based frameworks like Vue. For example, below is a Vue app that renders the yin yang symbol:

const app = new Vue({
  template: `
    <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="-40 -40 80 80">
      <circle r="39"/>
      <path d="M0,38a38,38 0 0 1 0,-76a19,19 0 0 1 0,38a19,19 0 0 0 0,38" fill="#fff"/>
      <circle cy="19" r="5" fill="#fff"/>
      <circle cy="-19" r="5"/>
    </svg>
  `
}).$mount('#content');

You can use conditional rendering with v-if and other Vue directives with inline SVGs as well. For example, the below Vue app lets you get rid of the yin (black) or yang (white) side of the symbol and throw the universe out of balance.

const app = new Vue({
  data: () => ({
    yin: true,
    yang: true
  }),
  template: `
    <div>
      <div>
        <div>
          <input type="checkbox" v-model="yin"> Yin
        </div>
        <div>
          <input type="checkbox" v-model="yang"> Yang
        </div>
      </div>
      <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="-40 -40 80 80">
        <circle r="39" v-if="yin"/>
        <circle r="39" v-if="yang && !yin" fill="#fff" />
        <path d="M0,38a38,38 0 0 1 0,-76a19,19 0 0 1 0,38a19,19 0 0 0 0,38" fill="#fff" v-if="yang" />
        <circle v-if="yang" cy="19" r="5" fill="#fff"/>
        <circle v-if="yin" cy="-19" r="5"/>
      </svg>
    </div>
  `
}).$mount('#content');

Exporting SVGs

SVGs enjoy widespread browser support, but some apps don't support SVG images. For example, Slack doesn't show a preview of uploaded SVG images:

The workaround is to use an npm module to convert your SVG to a PNG. In the past I've used sharp for this.

const sharp = require('sharp');
const fs = require('fs');

const buf = fs.readFileSync('./yinyang.svg');

// Use sharp to convert the SVG to a PNG, remember
// that `toBuffer()` returns a promise!
sharp(buf).png().toBuffer().then(out => {
  fs.writeFileSync('./yinyang.png', out);
});

Once you have a PNG, you can upload the PNG to Slack. For example, you can use a pure SVG charting library like Frappe to create charts, then convert them to PNGs using Sharp so you can automatically upload them to Slack.

SVG For Logos

Many popular sites display their logo using SVGs. For example, Twitter's logo is an SVG:

SVG files are tiny: Twitter's logo is only a couple hundred bytes. You can even inline them in your HTML, so you don't need an extra HTTP request to load your logo. There are substantial performance benefits to using SVGs over JPG or PNG for icons and logos, because SVGs are typically much smaller.

Moving On

SVGs are much more useful than most developers give them credit for. Because they're defined in a human-readable plain text format, you can tweak SVGs without paying for Photoshop. Because browsers have native SVG support, you can use frontend frameworks like Vue or React to draw SVGs. That makes it easy to get creative with visualizations: Gantt charts, Tree maps, GitHub-style heat maps, and more. Try building your own SVG visualizations from scratch: you'll be surprised how easy it is to build something neat.

Found a typo or error? Open up a pull request! This post is available as markdown on Github
comments powered by Disqus