Icons have been part of applications since ages. Also most websites rely on icons. There were several ways to use them. First we used plain files then image sprites to reduce requests. Nowadays everyone uses icon fonts like font-awesome or glyphicons.
They are infinetly scaleable and styleable with css. The downside is they use pseudo elements for displaying. This is not only difficult to handle but also non-optimal for accessibilty.
A famous CSS-Tricks post brings SVG icons into play. The are also scalable and they behave like normal images. But we also want to have a sprite to not load any images seperatly and kill our servers and our sites performance. The proposed version is to create sprites with grunt or gulp using the symbol-trick. It's basically add every icon to a hidden sprite-image and give every icon an id-property.
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="beaker" viewBox="214.7 0 182.6 792">
<!-- <path>s and whatever other shapes in here -->
</symbol>
<symbol id="shape-icon-2" viewBox="0 26 100 48">
<!-- <path>s and whatever other shapes in here -->
</symbol>
</svg>
Then you can do this
<svg class="icon">
<use xlink:href="#shape-icon-1" />
</svg>
This is a pretty clever idea if you don't have a framework like mithril. You still have the burden to create svg-sprites and you have to have on hidden element that holds the icons (which is no really problem, but verbose)
If you use browserify and mithril (what I strongly entourage you to do) there is an even simpler way. Browserify lets you include any file you want and base64 encodes them into the build. So first put your icons in a directory of your choice. Then you create a module called icons.js
:
var fs = require('fs');
var m = require('mithril');
function icon(svg) {
return m('.icon', m.trust(svg));
}
module.exports = {
icon0: icon(fs.readFileSync('directory_of_your_choice/icon0.svg', 'utf8')),
icon1: icon(fs.readFileSync('directory_of_your_choice/icon1.svg', 'utf8')),
icon2: icon(fs.readFileSync('directory_of_your_choice/icon2.svg', 'utf8'))
};
Browserify spots these files are read with fs.readFileSync
loads them as Base64-encoded strings. The module then creates a div
with class icon
and embeds the svg into that div. The m.trust
function prevents the svg from beeing html-encoded.
Now you have a module with all your icons in it. To use them simply embed them into your view functions:
var icons = require('./icons');
function myView(scope) {
return m('.content', [
icons.icon1
'My fancy icon div'
]);
}
The output then looks something like this
<div class="icon">
<svg>
<!-- <path>s and whatever other shapes in here -->
</svg>
</div>
Pay attention to use the brfs-transform along with browserify. This embeds the readFileSync-ed files.
browserify -t brfs index.js
The advantages of this usage are:
- No building svg sprites
- Advantages of SVG over Fonts (better handling and styling)
- One less file, since the icons are embedded in your javascript file
- Easy to maintain
- Minimal code
- Pretty output
- Mithril-way of doing things :)
👍 I'm gonna try this tomorrow. This is very clever.