There is another, newer article on this subject that covers some newer information.
Inline SVG is an awesome way to use SVG because, among other reasons, the individual shapes that make up the graphic can be scripted and styled. The shapes are right in the DOM. But does that mean we have to define those shapes right in the HTML on every page? Nope, we can <use>
to reference them from elsewhere. Ideally, that “elsewhere” is an external file, because that means that file can be cached by the browser, efficiency!
Here’s what I mean:
<!-- `<use>` shape defined ON THIS PAGE somewhere else -->
<svg viewBox="0 0 100 100">
<use xlink:href="#icon-1"></use>
</svg>
<!-- `<use>` shape defined in an EXTERNAL RESOURCE -->
<svg viewBox="0 0 100 100">
<use xlink:href="defs.svg#icon-1"></use>
</svg>
So yeah: external resource = the way to go.
But, the external resource way doesn’t work in any version (up to 11 tested) of Internet Explorer. Even the ones that do support inline SVG: 9, 10, 11.
Fortunately, Jon Neal has a clever solution. It’s a little script called SVG for Everybody. The idea is this: just use <use>
as if it works, and the script will handle it in IE 9, 10, 11. A polyfill, except just for this scenario (it doesn’t make this work anywhere that doesn’t already support inline SVG use).
It works like this:
- If the browser is IE 9, 10, or 11 (User Agent sniff, but that’s the whole point here).
- Ajax for the SVG file referenced
- Find the needed bit, based on the ID referenced (e.g. #icon-1)
- Inject that into the
<svg>
on the page

I think inline SVG is damn useful and this (tiny) script means you can use it in a more responsible (cacheable) way.
What exactly is the limiting factor for IE? Using
<use>
at all, or using<use>
with an external resource?Well if I got it right, IE10 and down won’t render a SVG defined with DEFS and called with USE
Exemple : http://www.dblok.net/svgtest.html
With http://netrenderer.com/ I see that only IE11 renders the SVGs
And I think that IE11 renders the SVG with DEFS/USE, but only if the source SVG is not external (but I will let Chris confirm that)
<use>
with an external source doesn’t work in IE 9, 10, 11. That’s the whole point of the article =)Great article thanks for sharing this polyfill…
I have tried getting this to work on other occasions and have been unsuccessful…does anyone know of a known good working demo of this on the web somewhere that one could download and play with…
I learn best by reverse engineering known good working files…
I got to work…will try the polyfill next….again thanks for all this info on SVG…
Michael!
I link up a working demo in the article: https://css-tricks.com/examples/svg-for-everybody/
Hey Chris, Gilles here, we met à BTConf (the tall french guy). Did I told you that you were awesome there ?:)
That’s is the idea I kinda had on monday. That’s what i was trying to tell you :
My idea is to put your SVG code in a JS file, where it is a javascript string with a document.write.
Here is a file like this, with two svg n it : http://www.dblok.net/svgtest.svg.js)
And here is a pen integrating this file in js, and then calling two separate SVGs via a USE tag http://codepen.io/gfra/pen/xzGIo
No JS ajax call, no multiple http requests, and the file js is cached after the first visit mù!
My SVG/JS file is a bit crappy, I made it fast last monday in my hotel, I didn’t have THE INTERNET to help me make it in a well formatted syntax
Pretty clever!
You’d just want to use a build tool to create that JS file for you, just like you would the defs.svg file.
My only concern is
document.write
. That’s generally considered bad I think (usually referred to as “evil”) although I can’t remember exactly why. I think it’s performance related in how it stops parsing and execution of stuff.Yeah, it’s pretty nasty when it comes to performances (I think it rebuild the DOM like Satan himself would do it, or even worse) but the idea was worth the try !
FYI I also tried this technique
It is quite nasty too but … it also works !
Oh, I think my tricks still wont work in IE …. The polyfill go and grab the actual SVG code of the corresponding ID…
My bad !
Does Opera browser allow tags?
Good polyfill! I’ve created a small gulp plugin gulp-svgstore that combines svgs into one, might be useful to mention it here. Have been using it with gulp-inject into body tag, but now switched to external source.
I was just trying this technique and I saw that I was using everything exactly right. However, it wasn’t displaying anything in Chrome. I checked the console and found that I got a “Unsafe attempt to load URL” error. I threw this in CodeKit really quick and it worked perfectly. Maybe everyone knows this already, but you can run into some cross-domain issues with this technique when developing locally, if you aren’t developing with a server. I hope this helps someone. Thanks again for this post Chris, it happens to be super timely for me.
Why svg or Icon fonts used pages some times gone completely black color in Firefox 29?, Scroll mouse it will be show again Partially. It is a Firefox bug?
Why an “even”?
Hey Chris,
first of all, thanks for the article. I have a question about using the tag. Is it still possible to access the paths of the SVG? Let’s say, I call a SVG via
<use>
tag in between an anchor tag. Is it possible to say something likea:hover svg { fill: purple; }
?Tanks for your awesome work!!!!
But still no HTML Iinncludes …
I found out an issue in IE9. Console writes: “The data necessary to complete this operation is not yet available. File: svg4everybody.js, Line: 37, Column: 4”. Any idea?
Not sure if someone posted this. But Here it is, in Grunt to take the manual parts out.
https://www.npmjs.org/package/grunt-svg-combine
I don’t understand the advantage of this Chris. Why is serving up the svg shapes from an external file better than just including the shapes at the top of each page (for example via a php include) as you suggested in your previous article?
After all, svg shapes are often described by very small text files, and by including the shapes at the top of the page, you’ll be saving 2 server requests (one for the svg file, one for the js pollyfill).
Is caching really going to make a big difference here?
Say there is 15k of icons in a chunk of HTML at the top of each document.
etc.
If they are in an external resource and cached
etc.
The more pages you expect people to visit and the more size-of-icons you have, the bigger the impact.
Yes. Caching always makes a difference, even if you can’t notice it in some contexts.
But because it adds an http request at the first call of your page, it may be a good question. The very first call of the page won’t be very fast, if it must call your CSS, your JS and JS Libs (not always hosted on CDNs) and another file for you SVGS, and wait for all that to be dowloaded to start render the page.
I read recently that to boost loading times, Google advice webdevs to define styles for the first half of the page directly in the HTML code, so that the page can start to render before the whole CSS file is loaded. It is an incredibly strange advice to give but, hey, it’s Google, what do you want to do against them.
I am still puzzled by this advice. Anyway, with this idea in mind, maybe you want to include your SVGs in your page, but I don’t think it is a good idea.
Thanks Chris, that’s a useful explanation.
In respect to “why” at the very top, is it not actually as a result of it being a replaced element – coming from the OS level? The fact that it’s a self-closing tag shouldn’t really play into it too much, right?
Is the closing tag something that’s born out of the requirement for it to contain content? Maybe that should be mentioned to avoid confusion towards this non-standard markup.
Otherwise, looks awesome, can’t wait for greater shadowDOM support in the future.
I totally loved this method when I tried it out and already thought that this is the future for SVG icons – but then I found out that it doesn’t work in Android, even 4.2, so it’s totally useless. :(
Not working in Android is a pity, true. I don’t care about IE8, but Android is somewhat important :P
For another reason I tried to use a real external path to reference a SVG-file.
It’s a bit odd…
Seems like this works (same with 127.0.0.1):
While this is failing (internal network IP):
Files from real external sources are failing as well. Like:
Or did I miss something?
p.s.
The code block function is not showing my code, that’s why I left out the ‘>’ ‘<'
see here:
I think this is a limitation of the browser, that cross domain files can not be loaded, only on the same domain. I also tried that (Chrome for me).
Yep, you’re right. Didn’t know it’s handled like this.
Should have seen it by the pattern…
Thanks!
Bit late to the party here, but while trying out svg4everybody (which is awesome) and the IE8 fallback, I noticed that it doesn’t transfer any of the classes from your
element to the
. This means if you’ve styled the svg – such as floating – it won’t apply to the IE8 fallback.A quick fix, if you’re using Selectivizr, is to do
.my-svg-icon ~ img
– it appears IE8 by default treats the opening and closing “ as individual elements that it doesn’t understand, meaning they, theuse
tag and theimg
are all siblings.Arg typo – it doesn’t transfer any of the classes from your svg element to the generated img tag.
And by default IE8 treats the opening and closing svg tag as individual elements.
What happened to the preview post option!
Just can’t seem to get this to work at all.
Using latest Chrome I can ‘use’ SVG when the SVG file is included into the page, but then when I apply this method it all falls apart. Nothing seems to display where the SVG should be.
Been over the code so many times. Not sure what to make of it.
Any debug tips would be appreciated.
So, turns out a nice fresh SVG from Iconmoon works just fine but, run it through SVGO and it dies.
Doesn’t seem to work in cordova app, I had to inline svg with defs inside body. I guess it is because of file:// protocol.
This only seems to work if I specify the:
As such, when using grunt-svgstore to generate my sprite I had to add:
I’m not sure if that’s considered correct practice?
Also, the
viewBox
size seems to work when placed on the external SVG file, so if that’s in the gruntfile (as above) then we can trim down the HTML a tiny bit: