CSS: Using raw svg in the URL parameter of a background-image in IE

So, I'm trying to do something like this:

div {
    width: 100px;
    height: 100px;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: 100px 100px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' style='fill:red; stroke:none'><rect x='0' y='40' width='100' height='20' /><rect x='40' y='0' width='20' height='100' /></svg>");
}

See here: http://jsfiddle.net/trxkcx41/4/

This works beautifully in current versions Chrome, Safari (OS X and iOS), and Firefox. However, the SVG doesn't appear at all in IE 9, 10, or 11.

Is that because this is not supported in IE, or because I'm doing something wrong?

[UPDATE WITH SOLUTION]

Thanks to hungerstar, I've got this working. To summarize his recommendation, I needed to make the following changes:

  1. Change the data type from data:image/svg+xml;utf8 to data:image/svg+xml;charset=utf8 (i.e., charset= is required)

  2. URL encode the svg. To minimize the URL-encoding, use ' instead of " to enclose the attributes. So, in my case, only the < and > needed to be encoded.

To, ultimately, my CSS looked like this:

    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' style='fill:red; stroke:none' %3E%3Crect x='0' y='40' width='100' height='20' /%3E%3Crect x='40' y='0' width='20' height='100' /%3E%3C/svg%3E");

Solution 1:

IE does appear to support using utf8 in a data URI, it's simply being more fussy about it. See this Codepen Blog Post for more details but here are the highlights:

The author points to RFC2397 and highlights:

data:[<mediatype>][;base64],<data>

The <mediatype> is an Internet media type specification (with optional parameters.) The appearance of ";base64" means that the data is encoded as base64. Without ";base64", the data (as a sequence of octets) is represented using ASCII encoding for octets inside the range of safe URL characters and using the standard %xx hex encoding of URLs for octets outside that range. If <mediatype> is omitted, it defaults to text/plain;charset=US-ASCII. As a shorthand, "text/plain" can be omitted but the charset parameter supplied.

  • Most browsers are lenient about the charset= string, but it's required for Internet Explorer. That means you need to use ;charset=utf8, instead of ;utf8,.
  • From above, "Without ";base64", the data (as a sequence of octets) is represented using ASCII encoding for octets inside the range of safe URL characters and using the standard %xx hex encoding of URLs for octets outside that range." Which means you will have to percent-encode characters that aren't URL-safe. For example, <svg> to %3Csvg%3E. You can minimize the amount of percent encoding that needs to be done by using single quotes ' instead of double quotes ".

Solution 2:

For IE9 I have to URL encode the whole SVG code.

This is my workflow for SVG background images.

First paste SVG code here to optimize it: https://jakearchibald.github.io/svgomg/ ("paste markup")

You can remove the "viewBox" but be sure that "width" and "height" are defined in the SVG code, IE9 needs this for better CSS implementation.

Now you have something like:

<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M0 0h100L50 50"/></svg>

In this case I have to add a fill color, because there was none defined. so I add:

fill="#cc0000"

to the end of the path element (if there are a couple of path elements in a group ("g") you have to put this fill color to all of these. If the SVG has strokes do the same with the strokes like stroke="#cc0000").

Now we have the following SVG code:

<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M0 0h100L50 50" fill="#cc0000"/></svg>

Now encode the whole SVG code here: http://meyerweb.com/eric/tools/dencoder/

so you get:

%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%3E%3Cpath%20d%3D%22M0%200h100L50%2050%22%20fill%3D%22%23cc0000%22%2F%3E%3C%2Fsvg%3E

At least put this whole thing together in your CSS:

.apple {
    background-image: url('data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%3E%3Cpath%20d%3D%22M0%200h100L50%2050%22%20fill%3D%22%23cc0000%22%2F%3E%3C%2Fsvg%3E');
    }

Some advantages that drove me nuts:

Be sure to wrap the SVG background code with ' in the CSS because inside the SVG we use "!

Be sure to use

data:image/svg+xml;charset=UTF-8

nothing else.

Now the SVG is displayed with the color "#cc0000" (dark red) even in IE9 on windows.

With this URL encoded SVG I still can change the color with a PHP variable. For example I just replace "cc0000" with:

<?php echo preg_replace("/#/", "", $textcolor); ?>

I do this for WordPress templates so the customer can pick the icon color in the backend.

enter image description here