SVG symbol a Good Choice for Icons

Avatar of Chris Coyier
Chris Coyier on (Updated on )

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

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
original-file's-desc


grunt-svgstore does this now, thanks to TxHawks and Fabrice!

Why <symbol> is better for icons

Just to put a point on it:

  1. The viewBox can be defined on the symbol, so you don’t need to use it in the markup (easier and less error prone).
  2. title and desc tags can be added within the and they kinda “come along for the ride” when the symbol gets used, making accessibility easier to do right.
  3. Symbols don’t display as you define them, so no need for a block.
  4. This is probably what was invented for anyway.

Demo

It works:

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