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.
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>
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>
<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:
- We can style all the separate parts
- 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="/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.
That was my idea! Chris has stolen my glory :D
I totally learned about
<use>
from you! Remember https://css-tricks.com/svg-tabs-using-svg-shape-template/I learned hundreds things from you) thanks Chris!
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/
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.
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.
Thanks for that link
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.
I am new to grunt and I get the following error when I try to run grunt.
Loading “svgstore.js” tasks…ERROR
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.
Hey Terence, I played around with this and haven’t been able to get it to work. Have you had any luck?
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?
Sorry there where an issue with the npm package.
It is fixed in version 0.0.2.
Seem to be getting different errors now – starting at
Try updating npm to the latest version.
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.
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.
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 ?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.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)?
You can use the same SVG sprite with background-image, but without inline embedding you won’y be able to style SVG from CSS.
Robert is correct, unfortunately. However there is a workaround that works fairly okay. See Ian Feather’s article on the matter, it’s a very good explanation.
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.
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.
What’s to say, using this thinking, that we can’t just use svg for all images?
Photographs.
@Eric
But even photos and other raster images can be embedded within SVG for easy re-scaling.
So… What’s the over/under on when we finally start doing all our layout in svg and use foreignObject for content.
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.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.
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.
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.Good job bro. You’re master. I am newbie and want to learn more about css and also SVG Sprites..
This is awesome! However, adding the SVG to the HTML basically means no caching of the SVG (which can be a very large file if you need many icons); but I think there’s a simple solution for it:
We can use a relative link to the SVG file followed by the id. I made a demo page for testing. It seems to work perfectly everywhere; but if you try it locally, it fails in Chrome, with an error like this:
When hosted on a server, it’ll work in Chrome as well. This approach solves the caching problem of putting the SVG in the HTML, and makes the HTML much cleaner too.
I updated IcoMoon’s sprite generator today after reading this article. If you use IcoMoon to generate your SVG sprite (using the SVG button rather than Font), it puts the SVG inside the HTML because otherwise, the demo won’t work locally in Chrome, which would be confusing. So I’m hoping to find a solution for Chrome. Maybe it’s just a bug?
Yeah I’ve seen that too. I just made a local domain to test it and it works fine. It’s just the same kind of thing as needing a real domain to do ajax testing.
The real strike against linking to the .svg file right from
<use>
is that it fails in IE-anything. I updated the article with some stuff from Jonathan Neal that seems to work. See his demo: http://sandbox.thewikies.com/svg/It is worth mentioning that you can use ajax request to load icons sprite file, so it would be cached by the browser. Vanilla js or JQuery
Clever! Deferred loading AND utilizes browser cache AND stop document caching bloat.
Do you happen to know of an example of this? I think I understand the example and would like to try but I cannot load the SVG sprite file in with PHP, not an option for me. Thank you.
Great article and insight – I will give this a spin on my next project and probably update a few in the mean time.
take a look at Iconmelon project then ;) It uses the same technique
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?
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.
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 CSScolor
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.Could use this to create your svg’s. http://glyphter.com/
Regarding accessibility, yes you should use
<title>
to get the same effect asalt
on an<img>
.The -Tags in the code block in “Combine the .svg files” are not closed
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)
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..
All of the examples I found go straight in to
options{}
andfiles{}
but in my case I had to enclose them indefault{}
– finally figured this out by checking out the gruntfile.js within node_modules/svgstore itself.Whoops. Missed a curly in the above code. Use:
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.
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
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:
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
).there are many interesting informations here, thank you for sharing with us these steps!
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?).
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.
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!
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.
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.
List of SVG properties that can be controlled by CSS is here. Just in case somebody will need it
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.
Chris,
In regards to location of the defs code, you wrote:
So why is it at the bottom in CSS-Tricks?
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.
The Gulp equivalent of grunt-svgstore is gulp-svg-sprites.
I have a folder full of SVG icons in my
src
folder. I run them throughgulp-svg-sprites
usingdefs: true
, to produce asprite.svg
file in mypublic
folder. Then I generate the HTML from a jade template in mysrc
folder which includes the SVG sprite at the top:Note: It’s really difficult to post comments with code in without getting errors from Securi
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.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
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…
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.
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?
Sorry, didn’t notice:
Thanks
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!
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.
Thanks for the reply.
How would you go about linking to it externally, maintaining the ability to style the svgs AND support IE?
I think I’m missing something here.
Is there an obvious fallback solution for this method?
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…
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.
I see that you already answered how you can do it in your article below. Thanks for putting this both of these articles together.
More specifically, I just wrote today about how to use an external source with (inline) SVG: https://css-tricks.com/svg-use-external-source/
If anyone wants a gulp-variant of the grunt plugin, check this out: https://github.com/coma/gulp-svg-icons
It’s kick ass!
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?
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…
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.
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.)
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.
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 inlinefill="..."
from the compiled SVG file. I’ve had a lot of headache trying to do.icon-x { fill: red; }
to not avail because my SVGsymbol
s had inline fills that were overriding my CSS. Hopefully someone finds this useful.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!
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:
http://codepen.io/greenchameleondesign/pen/tubJz
Interestingly, it seems to fire if you use $(‘.element’).click(function(){ … }) rather than $(document).on(‘click’, ‘.element’, function(){ … });
Just in case anyone is finding the same problem – it has been picked up as a Chromium bug and should be fixed in a future release. Still broken in IE though I guess :/
https://code.google.com/p/chromium/issues/detail?id=382872
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.
http://codepen.io/denilsonsa/pen/vdeLu
Hey Chris, for me the php include_once command just does not work.
What can I do?