SVG Sprites

March 16, 2018 Tony Montemorano

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. And more importantly, 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 icons 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 (Scalable 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 scalable 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 its 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 its 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 SVGs 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 won't 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 that’s serving the actual page, in order to work. If this isn't possible, you still have some (less desirable) options.
    • Use the SVGs inline.
    • Add the sprite to the page/component(s) it’s used on.
    • Individual <img> tags 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 SVGs with CSS is easily one of the coolest features. But there are some limitations to be aware of:

  • Referencing SVGs with <img> tags means you can't manipulate them with CSS.
  • When using SVGs inline, you can manipulate the paths individually. But 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) tags 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, that 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: 

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 artboards 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.

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 its parents). This is great for auto-magically changing icon colors without writing extra CSS.

Note: Despite possibly being the only value that uses camelcase, 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 fills 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:
https://codepen.io/allusis/pen/OQRrGW

Originally published on CodePen.

Previous Article
How to Build Code-free Dynamic Emails with Marketing Cloud
How to Build Code-free Dynamic Emails with Marketing Cloud

Displaying dynamic content in your emails no longer requires writing custom code. If you can drag-and-drop,...

Next Article
Marketing Cloud Connect Is Installed — Now What?
Marketing Cloud Connect Is Installed — Now What?

As a follow-up to Installing Marketing Cloud Connect in Salesforce, I wanted to share suggestions that will...