Last updated: 2/13/18

Introduction

An image sprite, defined loosely, is just a single image that contains other images.

Sprites even in a bitmap format (e.g., .jpg, .png), can save a huge amount of time, and will really up your icon-game. More importantly it will prevent a whole bunch of annoying individually loaded resources from being loaded on your pages.

When it comes to bitmap images however, supporting high-pixel density displays (i.e., mobile/retina screens) means that you need a separate, larger image at least twice the resolution to prevent the icon's from pixelating.

When you don't create higher resolution images, you'll see junky or pixelated images. It's sad looking, but there's hope, and it's called SVG (Scaleable Vector Graphics).

With SVGs, we don't have to worry about creating separate images. Yep, one size fits all. That means, when you pick up a 20k iPhone screen in a few years, your icons will still be just as crispy.

In this post we’ll review some important considerations, and illustrate some ways to implement a scaleable SVG sprite design/development process that could save you a metric ton of frustration — and give you crispy icons everywhere.

The Basics

Just like any SVG, you can open a sprite up in your favorite text editor and see your image's shapes in XML-based code.

The structure of an SVG sprite is slightly different than a single SVG image. For each icon in a sprite a <symbol> should be added as children to <defs>. Each symbol has it's own viewBox and id attributes.

The basic structure of a SVG sprite image:

  <svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>

    <symbol id="caret" viewBox="0 0 16 16">
      <polygon points="3,5 8,11 13,5" />
    </symbol>

  </defs>
</svg>

This sprite can be it's own separate file, or it can be placed right at the top of the page it's used on. If used on the page, you'll need to hide the sprite from rendering with a display:none or something similar.

SVG Sprite considerations

There are a few important points to think through when using SVG's in general, and the same goes for an SVG sprite. The approach you take to building your sprite may depend upon some of the considerations below:

Support

  • SVG sprites with an external image wont work in IE 9, 10, 11 without a polyfill. See SVG for Everybody.
  • Native applications still appear to prefer bitmap images.

The Domain

  • Sprite images need to be served from the same domain thats serving the actual page in order to work. If this isnt possible you still have some (less desirable) options.
    • Use the SVG’s inline
    • Add the sprite to the page/component(s) its used on
    • Individual <img> tag's for every icon

Adding svgs/sprites inline is going to create more markup that needs to be rendered every time the page loads. This may or may not affect your pages loading time a bit more than loading a single sprite image once (with an external image).

Icon Sizing

Keeping icon and viewBox sizes consistent for each icon is going to save you a lot of time, especially with sprites. If you aren't familiar with these attributes already, you can read up on them in this article: How to Scale SVG

Color Manipulation

Manipulating SVG's with CSS is easily one of the coolest features. But there are some limitations to be aware of:

  • Referencing SVGs with <img> tag's means you can't manipulate them with CSS.
  • When using SVGs inline, you can manipulate the paths individually. Keep in mind you're adding markup that will have to be loaded every time the icon is used.
  • When using external sprites the fills or strokes can be manipulated with CSS, but it's all or nothing. For example, setting a fill color will set the fill for every shape that doesn't have a fixed fill. (More on that later.)

Putting your sprites into action

Image setup

Since we can’t manipulate colors for shapes that have fills or strokes on them, we’re going to remove them for every shape or group that we want to change.

This is a good time to remove any junk comments, or empty <g> (group) tag’s if they exist. Just be sure you know what you’re removing!

Before removal:

  <symbol id="caret-down" viewBox="0 0 16 16" >
  <polygon points="3,5 8,11 13,5" fill=”#333333” />
</symbol>

After removal:

  <symbol id="caret-down" viewBox="0 0 16 16" >
  <polygon points="3,5 8,11 13,5" />
</symbol>

Note: if you have an icon with multiple shapes, and you only want to manipulate some, you can keep fixed fills (or strokes) on the elements that shouldn’t change. Keep in mind, no matter how much CSS you throw at them, they will not change if they have a fixed color.

Consistent icon sizes

See an example of mismatched icons below: viewBox Image

The Codepen icon is a bit smaller than the Github icon. This isn’t an extreme difference, but if we saw these next to each other, we’d certainly notice it.

There are a couple things we can do to make sure they render consistently:

  1. First and foremost, try to use icons from the same source to keep them as consistent as possible (Nucleo is amazing).
  2. If you can’t do that, throw them all in a Sketch file to be used as a working icon sprite source file. Use separate art boards or symbols for each icon and turn on the grid or create rulers to line them up and resize them. Export individually in the .svg format and copy and paste them into your sprite.

SVG Sprite Sample

Note: Most design tools will load the file with comments, and junk code. Sketch is no different, but luckily, the grouping does match the grouping of the elements in your artboard very closely.

Manipulating sprite icon colors with CSS

Now that we’ve removed the fill or stroke the icon’s defined shapes will be black by default. Gross, black doesn’t exist in the real world, plus chances are that’s not what you’re going for anyway.

Setting a specific color:

  .my-icon {
  fill: rebeccapurple
}

Setting a dynamic color:

  .my-icon {
  fill: currentColor
}

The currentColor value is the inherited color value (from it’s parents). This is great for auto-magically changing icon colors without writing extra CSS.

Note: Despite possibly being the only value that uses camel-case, currentColor is a plain old CSS. It can be used with other properties that use color values. Read more about currentColor on CSS-Tricks.

I find it helpful to create two utility classes for my icons sprites - .icon-fill for icons that have fill’s I’d like to manipulate, and .icon-stroke for the stroke-based icons.

  .icon-fill {
  fill: currentColor
}
.icon-stroke {
  stroke: currentColor
}

Applying this class to my icon references ensures that I never have to worry about the icon not matching the text color, which easily covers 90 percent of the use cases.

Adding icons to your page

Basic SVG reference in markup

  <svg class="icon-fill">
  <use xlink:href="img/sprite_base.svg#caret-down"></use>
</svg>

If the image exists on the page your referencing them on, you can omit the file path and just use #iconName

Break a leg

We hope you never bitmap unless you need to again! Check out a sample of the code:


2,468 0 23