Working with SVG sprites in Sass
Sass can make working with sprites much less of a headache. Here’s some techniques I use to handle PNG fallbacks and sprite positioning.
PNG Fallbacks
So you have an SVG sprite, but need a fallback for IE8. A great way to manage PNG fallbacks is by using a SASS placeholder selector and @extend to group your fallbacks into one rule.
Firstly, you’ll need Modernizr to detect SVG support. It will add a .no-svg class for browsers where a fallback is required.
If you override the background-image only, then you won’t need to redeclare the sprite position. If you’re using Illustrator to create your sprite, you can save out the PNG fallback using its Save for Web feature so both sprites have the same dimensions.
SCSS
.some-element {
background: url(../images/icons.svg) no-repeat 0 -40px;
.no-svg & {
@extend %no-svg;
}
}
.another-element {
background: url(../images/icons.svg) no-repeat 0 -80px;
.no-svg & {
@extend %no-svg;
}
}
// Placeholder selector, PNG fallback
%no-svg {
background-image: url(../images/icons.png);
}
Compiled CSS
.some-element {
background: url(../images/icons.svg) no-repeat 0 -40px;
}
.another-element {
background: url(../images/icons.svg) no-repeat 0 -80px;
}
.no-svg .some-element,
.no-svg .another-element {
background-image: url(../images/icons.png);
}
Notice how the PNG fallbacks are grouped together in one rule.
The .no-svg class is nested within each selector instead of within the placeholder selector itself because I ran into problems with the selector order with complex nested rules.
I’d also recommend using the below function to calculate the background position.
Sprite Positioning
// Distance between icons
$icon-offset: 40px;
// Calculate sprite position
@function icon-pos($position, $h-offset: 0, $v-offset: 0) {
@return (0 + $h-offset) (-($icon-offset * $position) + $v-offset);
}
Example Usage
// Set sprite background for classes beginning with .icon-
[class^="icon-"] {
background: url(../images/icons.svg) no-repeat;
}
// Use the second icon in the sprite
.icon-2 {
background-position: icon-pos(1);
}
// Use the third icon in the sprite, adjust position by 2px left, 4px top
.icon-3 {
background-position: icon-pos(2, 2px, 4px);
}
Note: icon position number is zero-based. This function assumes your sprite’s icons are stacked vertically. You can adjust the distance between icons with the $icon-offset variable.