Grow your CSS skills. Land your dream job.

Icon System with SVG Sprites

Published by Chris Coyier

I've been a big proponent of icon fonts. Lots of sites really need a system for icons, and icon fonts offer a damn fine system. However, I think assuming you're good with IE 9+, using inline SVG and the <use> element to reference an icon is a superior system.

First let's cover how it works.

A nice way to handle your icons is to have a folder full of .svg files.


That's one of the cool things about working with SVG - they are the source files.

They can be colored, not colored, multiple shapes, sizes, whatever.

You can let Illustrator (or whatever) save it however, with all the cruft that comes along for the ride:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<g>
	<path d="M50.049,0.3c14.18,0.332,25.969,5.307,35.366,14.923S99.675,36.9,100,51.409c-0.195,11.445-3.415,21.494-9.658,30.146 - yadda yadda yadda"/>
</g>
</svg>

Combine the .svg files

You can manually do this if you want. I've done it. You don't even have to look at the final file. Just call it svg-defs.svg or something.

It should just be an <svg> tag, with a <defs> tag (which just means you are defining stuff to use later), and then a bunch of <g> (group) tags. Each <g> tag will have a unique ID, and will wrap all the paths and whatnot for each icon.

<svg>
  <defs>

    <g id="shape-icon-1">
      <!-- all the paths and shapes and whatnot for this icon -->
    <g>

    <g id="shape-icon-2">
      <!-- all the paths and shapes and whatnot for this icon -->
    <g>

    <!-- etc -->

  </defs>
</svg>
Turns out <symbol> is probably a better choice than <g>. Read all about it!

Again you can do that by hand, but of course that's a bit laborious. Fabrice Weinberg has created a Grunt plugin called grunt-svgstore that automates this.

If you've never used Grunt, you can do it. Here's a screencast to get you started.

You can install it with:

npm install grunt-svgstore --save-dev

Make sure the task is available with:

grunt.loadNpmTasks('grunt-svgstore');

And then in the config:

svgstore: {
  options: {
    prefix : 'shape-', // This will prefix each <g> ID
  },
  default : {
      files: {
        'dest/svg-defs.svg': ['svgs/*.svg'],
      }
    }
  }
},

In the output file, svg-defs.svg, each icon (whatever paths and stuff from the source .svg file) will be wrapped up in a <g> tag with a unique, prefixed ID, and the file name (minus the .svg). Like:

<g id="shape-codepen">

Inject that SVG at the top of the document

Literally include it, like:

<!DOCTYPE html>
<html lang="en">

<head>
  ...
</head>

<body>
  <?php include_once("processed/svg-defs.svg"); ?>

Or however you want to do that.

It's gotta be at the top, sadly, as there is a Chrome bug in which this isn't going to work if defined later. Although... there is more to this story because as I type these words, the theme this very site is using has the icons defined at the bottom of the document and it works. Ughkgh confusing.

Use the icons wherever

Now you can use them wherever! Like:

<svg viewBox="0 0 100 100" class="icon shape-codepen">
  <use xlink:href="#shape-codepen"></use>
</svg>
Note that grunt-svgstore is now using <symbol> so you don't even need to use the viewBox!

Make sure you use those class names on the svg to size it.

/* Do whatever makes sense here.
   Just know that the svg will be an 
   enormous 100% wide if you don't 
   reign in the width. */
.icon {
  display: inline-block;
  width: 25px;
  height: 25px;
}

Yay: you can style them (and their parts) with CSS

One of the reasons we loved icon fonts is the ability to style them with CSS. This technique one-ups that in that we do everything we could there, and more, because:

  1. We can style all the separate parts
  2. SVG has even more things you can control, like special filters and strokes

The svg is (kinda) in the DOM, so JavaScript too. Here's some styling possibilities and a demo of this all at work:

See the Pen EBHlD by Chris Coyier (@chriscoyier) on CodePen.

Another way: IcoMoon

IcoMoon, which is known for producing icon fonts, actually does a fantastic job of producing SVG sprites as well. After selecting all the fonts you want, click the SVG button on the bottom and you'll get that output, including a demo page with the inline SVG method.

Browser Support

On the browser support front, the danger zones are IE 8 and down, Safari 5 and down, iOS 4.3 and down, and Android 2.3 and down. But if your policy is "the last two major versions" - you're looking at pretty much 100% support.

Remember that icons can be used as a supporting role only, like always accompanied by a word. If that's the case, support isn't too big of a deal. If these are stand-alone, and non-display would make the site unusable, that's a big deal.

I probably would go for icon fonts, as the support there is much deeper. Just make sure you do it up right.

This is going to get a lot better

Ideally we'd be able to do this:

<svg viewBox="0 0 100 100" class="icon shape-codepen">
  <use xlink:href="http://cdn.css-tricks.com/images/svg-defs.svg#shape-codepen"></use>
</svg>

This does work in some browsers, meaning you could skip the include at the top of the document. Doing it this way means an extra HTTP request, but that means you can utilize caching more efficiently (not bloat document caching). In testing, Jonathan Neal discovered you need to have the xmlns attribute on the <svg> for it to work:

<svg xmlns="http://www.w3.org/2000/svg">

But even then, no support in any IE. Unless you wanted to swap out the whole <svg><use> with an <object>, which does work. Jonathan Neal again figured this out:

/MSIE|Trident/.test(navigator.userAgent) && document.addEventListener('DOMContentLoaded', function () {
  [].forEach.call(document.querySelectorAll('svg'), function (svg) {
    var use = svg.querySelector('use'); 

    if (use) {
      var object = document.createElement('object');
      object.data = use.getAttribute('xlink:href');
      object.className = svg.getAttribute('class');
      svg.parentNode.replaceChild(object, svg);
    }
  });
});

His demo now also has a method which makes an Ajax request for the contents and injects that, which allows the fills to work in IE 9. Not as efficient, but more like a polyfill.

I imagine someday straight up <svg><use> linking right to the .svg will be the way to go. Or even perhaps <img> working with URL fragment identifiers on the SVG.


Browsers treat <use> like the shadow DOM:

Right now, we can target, say, an individual <path> with CSS, like:

.targetting-a-path {
  fill: red;
}

But that will affect all instances of that path. You'd think you could do:

svg.shape-version-2 .targetting-a-path {
  fill: red;
}

But that doesn't work. It crosses that shadow DOM boundary. Ideally you'd use the "hat" selector to break that:

svg.shape-version-2 ^ .targetting-a-path {
  fill: red;
}

But that's not supported yet either and it's not entirely clear if that's exactly how that will work or not.

"Versus" icon fonts

Vector-based: tie

Style with CSS: slight edge to SVG sprites (targeting parts, SVG specific styling like strokes)

Weird failures: SVG seems to just work (when supported). Icon fonts seem to fail in weird ways. For instance, you map the characters to normal letters, then the font loading fails and you get random characters abound. Or you map to "Private Use Area" and some browsers decide to re-map them to really weird characters like roses, but it's hard to replicate. Or you want to host the @font-face files on a CDN, but that's cross-origin and Firefox hates that, so you need your server to serve the right cross-origin headers, but your Nginx setup isn't picking that up right, SIGH. SVG wins this one.

Semantics: Not a huge deal, but I think an <svg> makes a bit more sense for an image than a <span>.

Accessibility: Maybe someone can tell me? Can we/should we give the <svg> a title attribute or something? Or a <text> element inside that we visually hide? Update: the <title> element might do. Or perhaps the <desc> element as used in this SVG access spec.

Ease of use: Tools like Fontello and IcoMoon are pretty good for an icon font workflow, but the folder-full-of-SVGs with Grunt squishing them together for you is even easier, I think.


Ian Feather posted an article about why they switched away from icon fonts as well and I agree with every single point.


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. Permalink to comment#

    That was my idea! Chris has stolen my glory :D

  2. John Holt Ripley
    Permalink to comment#

    Thanks for this.
    I thought it was worth adding that instead of mapping an @font-face icon to PUA or normal letters, there’s also the possibility of mapping them to similar Unicode equivalents.
    When used together, you get quite reasonable browser support:

    http://unicode.johnholtripley.co.uk/combined/

  3. I think one of the big things that draws people to icon fonts is the huge amount of icon sets. For people not able to design their own icons, this is super important. I’ve noticed a lot more great SVG icon sets lately though. A good round-up of SVG icons would be cool, like the one you did for font icons.

    • Don’t think of them as so different. It is trivially easy to change an icon font glyph into an SVG file.

      1) Make a new document in Illustrator (or whatever)
      2) Activate the icon font
      3) Type the character
      4) Convert-to-outlines
      5) Save as .svg

    • I will do a round of the best SVG icon sets avaiable at the moment.

  4. Aaron
    Permalink to comment#

    Interesting article. I like icon fonts because they rely on SVG which helps greatly with scalability.

    There’s one nifty way to make your own custom font icon(s) and that is by going to this link…

    Your Custom Font

    …and upload/drag your custom SVG icons/fonts.

  5. michael
    Permalink to comment#

    I still prefer icons because I can style them like text and style them WITH the text that they’re next to (color, shadow, line-height). This is especially useful for hover effects on buttons and if the client wants to re-size or recolor on a whim, it’s cake.

    Granted though, it really depends on the project and sprites are more applicable to some projects than others.

  6. aaron1919
    Permalink to comment#

    I am new to grunt and I get the following error when I try to run grunt.

    Loading “svgstore.js” tasks…ERROR

    Error: Cannot find module ‘cheerio’

    • Terence
      Permalink to comment#

      I’m having the same issue – really excited to use this tool (exactly what I need for a current project) but grunt seems to be giving me some issues. Fooey.

    • Aaron
      Permalink to comment#

      Hey Terence, I played around with this and haven’t been able to get it to work. Have you had any luck?

    • Terence
      Permalink to comment#

      No luck – I set up a new grunt setup to test it without anything else running and with the latest version of grunt, and still getting the same error.

      Anyone know of a work around for this?

    • Fabrice
      Permalink to comment#

      Sorry there where an issue with the npm package.
      It is fixed in version 0.0.2.

    • Terence
      Permalink to comment#

      Seem to be getting different errors now – starting at

      npm http 304 https://registry.npmjs.org/cheerio
      npm ERR! Error: No compatible version found: chalk@'^0.4.0'
      npm ERR! Valid install targets:
      npm ERR! ["0.1.0","0.1.1","0.2.0","0.2.1","0.3.0","0.4.0"]
      
    • Fabrice
      Permalink to comment#

      Try updating npm to the latest version.

  7. Roger V
    Permalink to comment#

    What are the ramifications of using an IMG tag and targeting the .svg file as the src? e.g. <img src="my-icon.svg">. I’ve tested on CodePen to verify this works (at least in Chrome). Is there something inherently wrong with this?

    • There is nothing wrong at all with that. I do it all the time. But with an icon system, you probably wouldn’t want to do that the dozens/hundreds needed for each icon. The goal is speed and reducing HTTP requests by having just one (or none) files that contain all the glyphs together.

    • Permalink to comment#

      The main goal here is that you can style your icons with CSS. If you use tag, you loose this ability. And the second goal – one http request surely.

  8. As you point out, including the whole sprite sheet inline on every request is sub-optimal.

    What about including it in an <object> tag, and using JS to copy on page load the SVG elements from the child document to the current document, so they can then be <use>-ed ?

    • Amelia BR
      Permalink to comment#

      It’s actually easier than that for real world (non-CodePen) situations. Just put all your icons into one SVG file, and reference the filename along with the fragment in the use element. The SVG file should be cached by the browser just like any other image resource used by multiple pages.

      But that doesn’t work if your “SVG file” is actually a link to a CodePen page, not an actual file. And it also doesn’t work (in most browsers with default security settings) if the file you’re linking to isn’t in the same domain as the file with the <use> element linking to it. “Domains, protocols and ports must match,” says the error on my Chrome console from the example I was trying to put together.

  9. Great technique. Does anyone know if there is any way to do this kind of ‘SVG spriting’ when the SVGs will be used as a background-image (probably in combination with background-size)?

  10. Filip
    Permalink to comment#

    I don’t like how despite the benefit of using SVG you still have to work with pixels to specify icon dimensions. I played with svg sprites a couple of weeks ago and came up with an interesting solution.
    I tested it on this this sprite-generating package and it works pretty well.

    • Alex Bell
      Permalink to comment#

      Well, you don’t have to use pixels (although CSS pixels are always there under the hood). You can size the wrapping element in any css unit (em, rem etc) and then size the element inside in percentages.

      Chris’s method has an arguable performance advantage over your svg-as-css-bg because in his the path data is loaded immediately inline, immediately, whereas in yours the SVG file doesn’t even get requested by the browser until CSS is loaded and parsed. Background images generally having a way of arriving last–which might be what you want, depending on your priorities.

  11. Joel Stransky
    Permalink to comment#

    What’s to say, using this thinking, that we can’t just use svg for all images?

  12. Adam
    Permalink to comment#

    So… What’s the over/under on when we finally start doing all our layout in svg and use foreignObject for content.

    • Amelia BR
      Permalink to comment#

      Highly unlikely. Positioning everything with SVG is essentially the same as positioning everything with absolute values. And although you can embed auto-sizing foreignObject elements (ignoring the current buggy-ness of implementations), you can’t easily (without scripting) adjust the rest of the layout accordingly.

  13. Great read…

    In the codepen showing the styled SVG icons…the fill for the youTube icon says the following:

    .shape-youtube {
    fill: url(#gradient);
    }

    …What is url(#gradient) ….I can not find what defines “#gradient”…

    Thanks,

    • Found the answer to my question…it is an SVG that is a gradient…and it is defined in the HTML…

    • It would have been nice there to define that gradient in the <defs> block along with all the shapes. I feel like that should work, but it doesn’t. Thus I moved it over to the same <svg> as the <use>.

    • Referencing fragment identifiers from your CSS could cause issues. Opera and FF needs path with the main svg file – url(icons.svg#element), while Webkits and IE needs just el id -url(#element). We could make it work by code preprocessing and then conditional CSS loading, but it is not that elegant though.

  14. Chris Z
    Permalink to comment#

    It may, in some cases, be required to set the namespace for xlink to work. It should come out looking something like
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16">

    Those xmlns’s can be a real pain sometimes.

    • Amelia BR
      Permalink to comment#

      Good point. If you need an xlink:href within a stand-alone SVG file, you need to specify the namespace. When the SVG code is inlined in an HTML 5 document, you can skip the declaration, so it’s easy to forget.

  15. Good job bro. You’re master. I am newbie and want to learn more about css and also SVG Sprites..

  16. deafwing
    Permalink to comment#

    Great article and insight – I will give this a spin on my next project and probably update a few in the mean time.

  17. Permalink to comment#

    Great post. But I noticed that SVGs are less responsive on mobile phones cause of high render time. What is most optimal solution for including icons in mobile phones? base64 encoding?

  18. It doesn’t look like :hover styles can be used to change fill color whether targeting the svg element or the group. Am i missing something or is this just some Shadow DOM event-bubbling malarkey?

    • You can use :hover and other pseudo classes.

    • Amelia BR
      Permalink to comment#

      You can use styles to target the icon as a whole, but not individual components within it; the styles will be applied in any case where inherited styles aren’t over-written by more specific styles.

      So you can change the default fill color and the default stroke color (and any other properties, like fill-opacity or stroke-opacity), but any parts of the icon which don’t use default values won’t change. You can also take advantage of the fact that you can use the keyword currentColor within the SVG to grab the value of the CSS color property in effect for that element, and so you can use that to create differently-coloured regions which you can control from the CSS.

      Demo here

    • Ah, I see. I was trying to overwrite a fill I had applied directly to the <group> already with a CSS rule applied to the <svg>. That’s no bueno.

  19. Permalink to comment#

    Could use this to create your svg’s. http://glyphter.com/

  20. Regarding accessibility, yes you should use <title> to get the same effect as alt on an <img>.

  21. Mr. Schnoerpsel
    Permalink to comment#

    The -Tags in the code block in “Combine the .svg files” are not closed

  22. Hey Chris

    There is also a “polyfill” plugin that generates a .png

    http://svgmagic.bitlabs.nl/

    I think that is a more elegant solution than embedding the SVG inside of an object ;)

    Best
    Lucas Dechow

    • This is a great idea! Unfortunately seems not working with inline svg. We have to fork it and add this functionality)

  23. Permalink to comment#

    For anyone having problems with this..

    Make sure you specify version 0.0.2 of svgstore in your package.json to get around the dependency issue (i.e. chalk / cheerio not defined).

    If you then have the issue I was stuck on (task running with no errors… but no files produced..) then use defaults in your gruntfile.js like so..

    svgstore: 
      defaults: {
        options: {
        },
        files: {
            'working-folder/output.svg': [dev-'folder/*.svg']
        },
    }
    

    All of the examples I found go straight in to options{} and files{} but in my case I had to enclose them in default{} – finally figured this out by checking out the gruntfile.js within node_modules/svgstore itself.

  24. Permalink to comment#

    Whoops. Missed a curly in the above code. Use:

    svgstore: 
      defaults: {
        options: {
        },
        files: {
            'working-folder/output.svg': [dev-'folder/*.svg']
        }
      }
    }
    
  25. Jake
    Permalink to comment#

    Thanks for this Chris. Instead of GruntJS, I’ve had some good mileage with gulp, using the gulp-svgmin plugin.

    You can also automatically generate PNG fallbacks for older browsers with the gulp-svg2png plugin.

    If you want to get really fancy, you could also generate 8-bit PNGs with 8-bit alpha channels.

  26. I’m fairly new to coding I’m not sure if this method will work on the Opera Browser, I come here to look and learn css code from you guys. Keep up the good work guys some of your tactics help me put my website together. Thanks guys

  27. The real pain here is not being able to use and style SVGs as pseudoelements. Often, Icons are purely visual, and are coded as :before and :after. With svgs, we have to do it as a background image and therefore use the ability to style with css.

    • Actually, you can use SVGs as pseudo elements, like so:

      a::before
          content: url('/img/icon.svg')
      

      I need to play around with what’s possible when using SVGs as pseudo elements or background images (defs, hover styling etc.). If we can achieve the same level of control as with inline SVGs then happy days!

    • I understand that you can use them as a background image but, as I said, you lose the ability to style the SVG properties (namely fill).

  28. there are many interesting informations here, thank you for sharing with us these steps!

  29. Ferdy
    Permalink to comment#

    I never tested this myself, but I keep hearing that the use of SVG can have a major performance penalty in some browsers. Can anyone confirm? (or deny?).

    • Amelia BR
      Permalink to comment#

      It really depends on the image, and what you’re comparing it with. Some types of graphics would require large PNG/JPEG files but can be quite compact when described as SVG, so that’s a bonus both for downloading as well as for use. It also depends what you’re going to do with it. Firefox in particular seems to have a hard time moving SVG images around — even when you’re not changing the image at all, the browser seems to recalculate the layout every time. This is a problem if using a set of SVG icons as a conventional sprite sheet controlled by background position properties, and another reason to use inline SVG with <use> elements for SVG icons.

    • I agree with Amelia, it depends on what you are doing. SVG tends to be slower then plain raster image, but in many cases it could be faster compared to 2x image resized to 1x for hight pixel density screens. From my experience point of view, I’ve launched about 4 large project with technique described in this post and never had problems with it. Christophe Schwyzer have made interesting tests that could be interesting for you.

  30. YoYurec
    Permalink to comment#

    My latest findings – Iconizr http://github.com/jkphl/grunt-iconizr
    Great tool for automated, full cycle SVG workflow – SVG sprites/ dataURI/ PNG fallback wia JS-loader
    Even better than GruntIcon!

  31. Skye
    Permalink to comment#

    For accessibility, I love the idea of using font icons with ligatures defined for entire words. Screen readers would read the icon as a regular word, and even copy-paste would give you the text version. It could be pretty nifty for something like a simple contact card with phone, email, etc.
    Of course, support is another matter.

  32. This is great and cool at the same time. But as I decided to try this on my own, I did the combining by hand (because I like to do it and mess terminal up really easily) and then did the php request after the body tag as Chris has above. The images load where I want, but there’s a huge chunk of white space now at the top of the document where the svg file is being brought in. Am I doing something wrong or am I missing some code somewhere to not make the svg file render on the screen as a huge chunk of space?

    • Hide your inline svg source by adding css styles. Something like style=”position: absolute; margin-left: -100%” on the svg tag should work just fine.

  33. List of SVG properties that can be controlled by CSS is here. Just in case somebody will need it

  34. Great article! But what about animation with transition css property?

    • Transitions working as usual.
      Animation don’t working across browsers so you would probably need to use js to animate your icons.
      You can’t use CSS transforms on SVG in FF and IE, so obviously you can’t animate and transit them too.

  35. Cory Streater
    Permalink to comment#

    Chris,

    In regards to location of the defs code, you wrote:

    It’s gotta be at the top, sadly, as there is a Chrome bug in which this isn’t going to work if defined later.

    So why is it at the bottom in CSS-Tricks?

  36. I made a Pen as a personal test. I thought I’d post it in case it’s helpful to other readers. I created the vectors in Illustrator and grouped the shapes I wanted to have the same colors, then I named the groups which became classnames. It helped me to do it graphically to understand what I was grouping together.

  37. dinofx

    It seems like SVG icons can no longer be cached the same way sprites or other referenced resources could be. For example, if I have 100 different webpages which all use the same set of icons, how do I avoid sending those icons back to the browser 100 times?

    Also, even just for a single webpage, if any amount of it is dynamically created, the browser will be fetching the same static SVG every time the page is loaded.

    • If you don’t need to support IE-anything, you can do <use xlink:href="sprite.svg#icon> and it’ll be cached like anything else. Otherwise yes, some page cache bloat, but certainly not a showstopper, at least for me.

  38. Paul Thomas

    Is there any way to include the SVG without having to know the viewBox size?

    i.e. :

    instead of:

    (and then style the icon width/height using CSS)

    As I have icons with several different canvas/viewBox sizes and it would be handy/quicker to include them without having to type out the viewBox

  39. Paul Thomas

    Also, there doesn’t seem to be a way to target sub elements of the svg using this method?

    If I embed the svg directly, I can target just one path and change it’s fill with css, if I employ the ‘use’ method as above then I seem to only be able to target the parent element, not sub elements.

    Am I missing something?

    I’m really keen to get this to work…

    • Paul Thomas

      Apologies, I just re-read the part about the shadow-dom which answered my question.

      Frustrating as otherwise this method seems great. Might just have to directly embed the SVG’s that require complex functionality and use this method for simpler icons.

  40. Ofer Groman

    First of all many thanks for this amazing article. I’ve been using png sprites via compass for a few years and I’m happy to see svg is finally kicking in.

    However, I’m a bit worried though – when including two or three icons there’s no question about performance here, but when you have a sprite with 20-30 svg icons and you include them all as markup in your html.. won’t that cause heavy performance issues?

  41. Thanks so much Chris! This is a really great article!!
    For those using Illustrator to create svgs – If you make your svgs on separate layers, there is a script you can install in Illustrator that will allow you to export the layers as individual svgs. This helped make my workflow much quicker. I then uploaded my svgs to Icomoon, then generated the svg sprite rather than the font.

    Chris, I totally agree with you when you say,
    “I imagine someday straight up linking right to the .svg will be the way to go.”

    That would be totally awesomeness, and keep things a little cleaner!

  42. veganarchist

    The article says that the sprite-sheet has to be included at the top of the document, right after the body tag, but noticed that CSS-Tricks actually has them at the very bottom of the body. So which one is it?

    • I think what happened here is that an earlier version of Chrome had as issue with this. They had to be at the top otherwise <use> instances below would fail. I remember confirming it, but I can’t now. So it’s either fixed or I’m crazy. Anyway, it’s better at the bottom IMHO because it doesn’t hold up rendering (probably) more important content.

      Although, linking to it externally is even better and I’ll be writing about that soon.

    • veganarchist

      Thanks for the reply.
      How would you go about linking to it externally, maintaining the ability to style the svgs AND support IE?

  43. Paul

    I think I’m missing something here.

    Is there an obvious fallback solution for this method?

  44. Dmitry

    Where icon fonts also fail is when font antialiasing is turned off in system. Some users (like me) like non-antialiased fonts better (for the sake of the eyes) and I even turn off remote fonts rendering in browsers, because many of web fonts are poorly designed for a non-antialiased scenario (my favorite is PT Sans, works like a charm in both cases).

    In this setup some icon fonts fail to deliver right icons and show squares. This might be browser-rendering related (for example, Chrome somehow manages to still correctly show font-based icons on some webpages where firefox fails mostly everywhere) , but still…

  45. Britton

    Chris, I noticed that you said you would be writing about how you could link to your SVG externally. Any idea how soon you would be discussing this, I am really interested in knowing what the proper way to do this. In your example you embed the SVG at the top using PHP, what would be the proper method for doing this if you were only using HTML and PHP is not an option.

  46. If anyone wants a gulp-variant of the grunt plugin, check this out: https://github.com/coma/gulp-svg-icons

    It’s kick ass!

  47. Rubén

    I’m planning to switch from PNG sprites to SVG sprites for a new project. I’m exporting the assets, a few simple icons and a logo from Illustrator CC and found that the file size is HUGE and I mean it. The whole PNG sprite is barely 8KB. The same SVG sprite is 3.5 Mb!!! Individuals icons score at 4 KB when exported in PNG and 40-50 KB when in SVG. This is insane. Heck I even tried to export the most simple shape (a plain square with a color fill) and it occupying 4KB!

    I assume that I’m doing something wrong cause I don’t find this sizes to be normal. However I can’t find what it is. Export option seem normal and set to a minimum.

    How much file size is your average icon?

    • Rubén

      Further research shows an unexpected behavior: The main art board is 1200×5000 px aprox. within it is where the icons sit. If I try to export an icon in place (i.e. delete de main art board > wrap the icon in its own art boar by double clicking with the art board tool > Then export selected art board as SVG) the result is a 3.5 MB icon. However if I do this: Copy the icon anywhere outside the main art board > Then wrap the icon in its own art boar by double clicking with the art board tool > Then export selected artboard as SVG. Everything is fine the resulting icon is <4KB.

      It is pretty weird since in both cases I end with a single 60x60px art board so the exported asset should be of the same size. It seems as if Illustrator were exporting the original 1200×500 art board even if it doesn't exit anymore.

      Anyhow I've moved this questions to Adobe forums. I'll keep you posted if I find more…

    • Paul

      I’ve had a terrible time with Illustratir and SVG. Mostly nailing decent export settings. If I don’t export preserving Illustrator editing capabilities then upon re-opening the SVG the artwork is all over the place. However if I maintain that setting I get a bigger file that won’t run through svgo for optimisation.

    • Britton

      After exporting my SVG sprite from Illustrator, I opened the SVG with sublime text and cut out a ton of unnecessary cruft. My SVG file went from around 70k to about 40k. One thing you may need to do in order to reduce your SVG file size is reduce the geometry of the icons. This may be a matter of unifying, subtracting, creating outlines of items. Also, sometimes using the simplify path tool can help too. (Obviously you have to be careful, not to destroy the fidelity of your icons in this process.)

  48. Britton

    One quick way to know if you are reducing the geometry is to go to save > svg > svg code and do a quick review to see if you reduced the geometry or increase it. Also, one other major way I cut my SVG down, was there were in some cases instances of base64 coded embedded images in there. Maybe some can explain why they are in there, but I removed them and didn’t see any consequences from removing them.

  49. Edward

    What this article doesn’t mention is if you want to use the CSS fill property to control the colour of the outputted icons, you’ll need to remove any instances of inline fill="..." from the compiled SVG file. I’ve had a lot of headache trying to do .icon-x { fill: red; } to not avail because my SVG symbols had inline fills that were overriding my CSS. Hopefully someone finds this useful.

  50. Alex

    Aren’t svg fragment identifiers not supported well, even on the latest and greatest mobile browsers (ie. Android 4+, iOS 6+)? I see problems in both where the elements simply don’t display consistently; sometimes they show up and sometimes they don’t.

    Love this technique though. Assuming I can figure out what’s causing my sporadic lack of icon display, it’s an excellent solution. Thanks for sharing!

  51. I have come across an interesting bug (?) whereby if you embed the SVG using ‘defs’ as part of a link (an icon for example) – the icon itself does not register a click event in jQuery, but clicking the text does. I think this is due to SVG events not bubbling up?

    If you embed the SVG directly, the link triggers regardless of whether you click the text or the icon.

    A simple test case I created can be seen here:

  52. I tried to experiment with this technique.

    I found that “ works fine on Chrome 35 and Firefox 29, but ONLY if the linked file is in the same domain, otherwise it is blocked by cross-domain policies.

  53. Hey Chris, for me the php include_once command just does not work.
    What can I do?

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