Skip to main content

How to embed an inline SVG in a CSS rule

Modern browsers allow you to embed the SVG almost as-is, with just a couple of characters that need escaping – no base64 required!

As part of redesigning this site, I was moving some of my small SVGs out of external files and inlining them in CSS rules. In my head, the way you do this is by base64-encoding the SVG and shoving it in a url() function, for example:

background-image: url('data:image/svg+xml;base64,PD94…')

Encoding all your SVGs with base64 has a couple of drawbacks: it’s impossible to read the SVG in the web inspector tools, and it’s a fairly inefficient encoding, making all the files a third or so bigger.

Fortunately the web has moved on since the last time I did this! You can now embed the SVG in close-to-unmodified form:

background-image: url("data:image/svg+xml;charset=UTF-8,<svg xmlns=%22http:/…");

The tricky part is encoding the SVG correctly – if the SVG can’t be read properly, you get a blank space in place of your image. The two characters that caused me a lot of hassle were double quote ("%22) and the octothorpe in hex colours (#%23).

But I got it working eventually, and now I have inline SVGs in CSS which are both readable and fairly efficiently encoded.

Working example

Here’s an example of how I’m using it in the site redesign, to replace <hr> elements with a line of orange squares:

<style>
  hr {
    width: 100px;
    height: 5px;
    border: 0;
    background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 25 5%22 width=%2225px%22 height=%225px%22><rect width=%225%22 height=%225%22 fill=%22%23ff9900%22/></svg>');
    background-size:   contain;
    background-repeat: repeat-x;
  }
</style>

<p>Hello world</p>

<hr>

<p>Goodbye world</p>