Grow your CSS skills. Land your dream job.

SVG `use` with External Source

Published by Chris Coyier

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:

  1. If the browser is IE 9, 10, or 11 (User Agent sniff, but that's the whole point here).
  2. Ajax for the SVG file referenced
  3. Find the needed bit, based on the ID referenced (e.g. #icon-1)
  4. Inject that into the <svg> on the page

It totally works.

I think inline SVG is damn useful and this (tiny) script means you can use it in a more responsible (cacheable) way.


Wanna learn more about SVG?

I have a full course available called Everything You Need to Know about SVG that covers the whole spectrum of SVG from the perspective of a web designer and front end developer.

Comments

  1. michael matyus

    What exactly is the limiting factor for IE? Using <use> at all, or using <use> with an external resource?

  2. 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…

  3. 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.

    • Gilles FRANCOIS

      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

      <!--[if IE]&gt;-->
      
      
      
      
      <!--[if !IE]&gt; &lt;-->
      
      
      <!--&gt; &lt;![endif]-->
      

      It is quite nasty too but … it also works !

  4. 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 !

  5. Does Opera browser allow tags?

  6. 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.

  7. Britton

    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.

  8. 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?

  9. joan

    Why an “even”?

  10. 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 like a:hover svg { fill: purple; } ?

    Tanks for your awesome work!!!!

  11. But still no HTML Iinncludes …

  12. Michal Erlebach

    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?

  13. 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

  14. Nye Hughes

    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?

    • 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.

      1. Visit page 1, 15k of icons come across the pipes
      2. Visit page 2, 15k of icons come across the pipes
      3. Visit page 4, 15k of icons come across the pipes
        etc.

      If they are in an external resource and cached

      1. Visit page 1, 15k of icons come across the pipes
      2. Visit page 2, NO TRANSFER, ALREADY CACHED
      3. Visit page 3, NO TRANSFER, ALREADY CACHED
        etc.

      The more pages you expect people to visit and the more size-of-icons you have, the bigger the impact.

    • Gilles FRANCOIS

      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.

    • Nye Hughes

      Thanks Chris, that’s a useful explanation.

  15. 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.

  16. 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. :(

  17. hannes
    Permalink to comment#

    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):

        svg viewBox="0 0 32 32" class="icon icon-1"
          use xlink:href="http://localhost/test-svg/sprites.svg#icon-undo" /use
        /svg
    

    While this is failing (internal network IP):

        svg viewBox="0 0 32 32" class="icon icon-1"
          use xlink:href="http://144.134.99.17/test-svg/sprites.svg#icon-undo" /use
        /svg
    

    Files from real external sources are failing as well. Like:

        svg viewBox="0 0 32 32" class="icon icon-4"
          use xlink:href="http://sandbox.thewikies.com/svg/cache.svg#twitter" /use
        /svg
    

    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).

  18. hannes
    Permalink to comment#

    Yep, you’re right. Didn’t know it’s handled like this.
    Should have seen it by the pattern…
    Thanks!

  19. 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, the use tag and the img 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!

  20. Paul
    Permalink to comment#

    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.

    • Paul
      Permalink to comment#

      So, turns out a nice fresh SVG from Iconmoon works just fine but, run it through SVGO and it dies.

  21. 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.

  22. David Paul

    This only seems to work if I specify the:

    version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
    

    As such, when using grunt-svgstore to generate my sprite I had to add:

      svg: {
            viewBox: '0 0 32 32',
            version: '1.1',
            xmlns: 'http://www.w3.org/2000/svg',
            'xmlns:xlink': 'http://www.w3.org/1999/xlink'
      }
    

    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:

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".