Looking for a better way to do SVG icons? Inline SVG might be your best bet, which you can learn about in this more recent post.
You could design an icon set where the icons all had the exact same aspect ratio. But that’s probably not typically going to be the case. The container around a little beaker icon might be tall and narrow. The container around a little fish perhaps short and long. You probably shouldn’t have to think too much about that, but unfortunately you kinda have to when you use an SVG icon system as I’ve described in the past, because you need to use the
viewBox attribute to describe that container/aspect ratio.
An improvement is to use the
element in SVG instead of directly referencing shapes (or a
), because you can define the
viewBox directly on the
and then not need one when you
it later in an
An example is in order.
Here’s two icons with very different aspect ratios, as you can tell from the artboard in Illustrator.
We could adjust them to all be placed within a consistent aspect ratio, but I find it’s more flexible and workable to know that your icons edges are right where the shapes stop, not with an arbitrary amount of white space around them.
The “Old” Way
If we go the
-block route, we might combine them into:
Then use them like:
That puts a good amount of onus on the implementer to get those
viewBox attributes correct in the markup. That’s one reason why might want to try and get all those icons at a consistent
viewBox="0 0 100 100" (or something), but then we have that kinda arbitrary whitespace thing going on.
The “New” Way
Enter Fabrice Weinberg and TxHawks. Fabrice works on grunt-svgstore, a Grunt plugin for creating the SVG sprites from a folder of SVG files. This kind of thing makes the SVG icon workflow quick and easy. That is, except for the fact that you need to know that dang
viewBox for each icon before you use it.
TxHawks suggested having grunt-svgstore at least put
data-* attributes on the
elements that wrap each icon, so there could be programmatic access to what it is supposed to be. But unfortunately SVG doesn’t allow those (it would have probably worked, but might as well make a build tool spec-compliant). It doesn’t matter though, because soon after, they suggested using
instead, which turns out to be quite a good idea.
Instead of using
to wrap all the icon shapes, use
, like this:
Note that the viewBox is defined for each icon and as you’re defining it as opposed to when you’re using it. That means using it becomes easier:
Easier, and less error prone.
And it gets better: you can add
grunt-svgstore does this now, thanks to TxHawks and Fabrice!
Why <symbol> is better for icons
Just to put a point on it:
viewBoxcan be defined on the symbol, so you don’t need to use it in the markup (easier and less error prone).
desctags can be added within the
and they kinda “come along for the ride” when the symbol gets used, making accessibility easier to do right.
- Symbols don’t display as you define them, so no need for a
- This is probably what
was invented for anyway.