https://jkphl.is/@jkphljkphlJoschi_Kuphaljoschi.kuphalJoschiKuphaljoschi@kuphal.netArticles RSS feed
iconizr
CSS & Sass icon kit creator · SVG & PNG sprite generator
iconizr is a free, Node.js / Grunt and command line PHP tool for processing SVG files to CSS icon kits, catering for the full range of devices and clients out there. It creates SVG and PNG fallback icon sprites, their data URI counterparts and the matching CSS in various flavours like Sass and LESS. It optimizes both SVG and PNG files in terms of size and offers some logic for CSS pseudo-classes. An online version is available at iconizr.com. Here are some details about the internals and ideas behind iconizr.
Although the SVG specification has been around since the early noughties, it hasn’t been widely adopted in web design until recently. Now that high resolution (retina) displays got more and more popular, there is a great need for a capable vector based image format that allows scaling to arbitrary dimensions without a loss of quality. SVG icons are only one of the many possible use cases, outperforming icon fonts in all aspects.
What about these icon fonts?
Filament Group’s Scott Jehl was the first to provide a free tool for creating SVG icon sets with PNG fallbacks: Grunticon, which is a very capable and probably the most popular solution for automating SVG icon kit creation at the moment. When I came up with iconizr in June 2013, however, I had a couple of reasons for taking a fresh approach to the same task:
- Very subjective, at that time, I was not a Node.js / Grunt guy, and requiring a Node.js installation for just running Grunticon seemed like an unnecessarily high hurdle to me. (To be honest: I nevertheless had to setup that Node server, not least for evaluating SVGO, but I still suppose many others out there not having a Node server handy. In the meantime, I also made a Node module and a Grunt plugin of iconizr, with an even extended feature set, but still I don't consider myself a Node / Grunt specialist ...)
- I had been working on squeezr before and wanted to transfer my experiences with PNG file optimization on my icons as well. (Just a little later, Grunticon also started supporting PNG optimization — I’m not sure if it still does at the time of this writing however ...)
- Grunticon doesn’t use CSS sprites — and I never understood why. I can’t find any reasoning for this, maybe except the rumour that CSS sprites were hard to manage. But hey, isn’t this all about automation so that one doesn’t have to bother with stuff like that? See below for some more thoughts on sprites.
- Grunticon is tied to SVGO as an SVG file optimizer. My experiments have shown that there are some rare cases where SVGO cripples the files it should optimize by swallowing some drawing details. Just try this sample file with a recent version of SVGO (v0.4.2 at the time of this writing) and you will find the little black dot at the left disappear in the “optimized” version. Furthermore, I found Scour to yield better results (i.e. smaller files) in the majority of cases. In any case, I thought, it would be nice to have some choice regarding the different tools involved in the whole process. As it turned out recently, there's only an incomplete Node port of Scour, so in fact the Node / Grunt versions of iconizr do also default to SVGO for SVG optimization. Using Scour is still possible, though.
- Finally, I’m working a lot with Sass, so I’d welcome this as an output option as well. The Node / Grunt versions of iconizr use Mustache templating for stylesheet rendering, come with customizable default templates for CSS, Sass and LESS and might even be extended by arbitrary output formats.
SVG to the rescue
SVGs can be a compelling alternative to icon fonts. Without going into excessive details here are some of the advantages compared to icon fonts:
- First of all, SVG is an XML based format, so it’s human and machine readable and can be easily produced, searched, indexed and scripted.
- SVG supports multiple colors, gradients, shadows, opacity and animations — to just name a few features.
- Compared to bitmap images, SVG files can be very small in size — as long as the pictorial motif and the used effects aren’t too complex. Additionally, as a text format, SVG supports a very efficient lossless compression, which makes it just perfect for being sent over the web.
- Client side SVG feature detection via JavaScript works pretty reliably.
- The combination of SVGs and PNG fallback images for less capable clients is outstandingly well supported across the current device landscape.
There are lot’s of great tutorials out there describing the possible ways for getting your hands dirty with SVG. So how to establish a smooth and, at best, bullet-proof workflow for your high quality web icons?
Grunticon as a starting point
Icon fonts have become very popular in the last few years, and in general they do a pretty good job. There are, however, some disadvantages which become increasingly important with the ever growing range of web enabled devices:
- There is quite a number of devices and clients out there that don’t support icon fonts, as a recent Filament Group research impressively demonstrated.
- Detecting a client’s support for @font-face can be a tedious challenge, as some of them don’t report their skills correctly.
- Although there are some efforts towards the implementation of multi-colored fonts, there’s still no commonly adopted standard, so icon fonts are still monochromatic.
Some thoughts on CSS sprites
CSS sprites are a well established means of reducing HTTP requests and saving download size. They are around for a long time and client support is almost guaranteed. Fortunately, you can use the spriting technique with SVGs just exactly the same way as you do with “normal” bitmap images. As opposed to SVG stacking — another really cool technique! —, client support for SVG sprites should be consistent with the support for regular bitmap sprites. So why on earth are they so rarely used? I didn’t spend too much time for research, but in a first attempt I couldn’t find any online generator for SVG sprites.
As mentioned before, I fail to comprehend why Grunticon doesn’t use sprites. It should be noted, first of all, that both Grunticon and iconizr prefer data URI icons over external files (although there are some serious concerns about the performance of data URIs on mobile platforms). The only reasons why a client would be forced to load the external images are: Either it doesn’t support data URIs at all, or the image’s file size exceeds the client’s length limit for data URIs (e.g. 32kB in Internet Explorer 8). Whatever the reason is, it’s only a very small minority of clients that is affected by these circumstances.
But even aside from that I believe that there is also another constellation where loading an external file outperforms the usage of data URIs: For my understanding, as soon as only on single image has to be loaded from an external location, it is performance-wise the most effective to load all of them from from there, packed into one compact sprite. I come to this conclusion because of these two assumptions (facts?):
- As soon as there’s the overall penalty of that additional HTTP request, the worst is already over again — especially when on a cellular network. So once the TCP connection is established, use it!
- Usually data URIs need more memory than the corresponding binary files because of the encoding that has to be applied (typically Base64). Loading a file from an external location will require less traffic than transferring it as a data URI. So again: If there’s an additional request anyway, then forget about the data URIs and use the request for loading a single compact sprite image. Under certain circumstances this could even allow the client to leverage it’s cache more efficiently ...
In summary, I can’t imagine even one single situation in which it would make more sense to load several single image files instead of one sprite. Of course one might argue that there’s a risk of loading “too much”, as not every single icon included in the sprite might be needed all over, but that would also apply to the even more bloated CSS file with embedded data URIs, which also prevent an independent caching of the image files by the way.
So in the end I made iconizr pursue a slightly different strategy than Grunticon: It will never produce CSS or Sass files mixing the two approaches. They will always employ either data URIs or external files, but never both of them.
So what’s going on behind the curtain?
The processing done by iconizr is pretty straightforward:
- It takes a directory of SVG files and starts processing them.
- In a first step, the SVG files are optimized (by freeing them from unnecessary cruft using SVGO or Scour) and sanitized (e.g. given a width and height in case they are missing).
- Next, an SVG sprite is created by merging the single files into one big SVG.
- iconizr then creates pairs of CSS resources (optionally in several different flavours like Sass or LESS as well) for the SVG icons, one of them referencing the external sprite, the other having the optimized single icon SVGs embedded as data URIs.
- Next to the PNG fallbacks: Both the single icon SVG files and the SVG sprite are rendered as PNG images using PhantomJS.
- All of the PNGs are optimized by several tools (Pngcrush, pngquant and OptiPNG) which results in significantly smaller files in most cases.
- Finally the corresponding CSS (Sass, LESS, etc.) stylesheet pairs for the PNG fallback images are created.
Additionally, iconizr features some logic for easy implementation of CSS pseudo-classes (like e.g. the :hover
or :active
states). Maybe the support for responsive icons is something that I’m going to add sometime in the future.
How to use iconizr in your projects
There are three main concepts of incorporating iconizr into your workflow. The most powerful one, at present, are the Node.js / Grunt versions. If you are already working with Node and Grunt, you will know how to fit them into your projects. At the moment, these are the only versions supporting Mustache based output rendering, so you will have to stick to them if you need to customize the default stylesheet output or support LESS and other arbitrary output formats.
If you need to convert many icons, some of them bigger than 300 kB in file size or 300 x 300 pixels in screen dimensions, you may also get the PHP command line version at GitHub and install it on your own server. You will be able to leverage all of iconizr's features by using the various command line options (be aware, however, that the PHP-CLI version currently doesn't support the Mustache option).
Finally, a somewhat limited online version is available at iconizr.com. Not all the features are exposed through the graphical interface, and only up to 50 icons — none of them bigger than 300kB and 300 x 300 pixels — may be processed at a time. On the other hand, the online version is so easy to use that you won’t want to miss it in your workflow once you got used to it. Simply try it yourself!