Responsive Sprites With SASS And Compass
I came across an interesting problem over the weekend and I thought it might be a good idea to share my solution. I was working on a site using SASS plus Compass and I had a number of images that I needed to set up as sprites in order to increase page load performance.
Setting up sprites with Compass is normally very easy. You simply add your sprite .png files to a directory within your project’s assets directory and point your config.rb
file there with the following line: images_dir = "assets"
.
For the purpose of this post, let’s say that your sprite assets have the following paths:
assets/icons/new.png
assets/icons/edit.png
assets/icons/save.png
assets/icons/delete.png
Once you’ve placed your icons and set your config.rb
file correctly, you simply create a new SASS partial called _sprites.scss
and add the following three lines:
@import "compass/utilities/sprites";
@import "icons/*.png";
@include all-icons-sprites;
This will give you the following classes, which you can then apply to your site’s markup:
.icons-sprite,
.icons-delete,
.icons-edit,
.icons-new,
.icons-save { background: url('/images/icons-s34fe0604ab.png') no-repeat; }
.icons-delete { background-position: 0 0; }
.icons-edit { background-position: 0 -32px; }
.icons-new { background-position: 0 -64px; }
.icons-save { background-position: 0 -96px; }
This is a great feature of Compass, but it falls short for responsive sites that need fluid-size sprites. On my project, I needed sprites that would resize to fill their fluid size containers. I did some digging, and ended up coming up with the following mix-in. Simply add this mixin to your _sprites.scss
file and then use it within a selector for the container element. Here’s the mixin:
@mixin responsive-sprite($map, $icon) {
$icon-file: sprite-file($map, $icon);
$icon-width: image-width($icon-file);
$icon-height: image-height($icon-file);
$sprite-file: sprite-path($map);
$sprite-map: sprite-url($map);
$sprite-width: image-width($sprite-file);
$sprite-height: image-height($sprite-file);
$space-top: floor(nth(sprite-position($map, $icon), 2));
@if $space-top == 0 {
$space-top: 0px
}
width: percentage($sprite-width / $icon-width);
display: block;
height: 0;
padding-bottom: percentage($icon-height / $icon-width);
background: $sprite-map;
background-size: 100%;
background-position:0 percentage(-1 * $space-top / ( $sprite-height - $icon-height ) );
}
Once you have this in place, you can use it as such:
.my-sprite-wrapper-div {
@include responsive-sprite($icons-sprites, save);
}
And voila, you now have responsive sprites which are auto-generated for you by Compass.
Further reading:
- http://compass-style.org/help/tutorials/spriting/
- http://www.wunderkraut.com/blog/responsive-retina-sprites-with-compass/2014-04-16
- http://www.hugeinc.com/ideas/perspective/using-compass-generated-sprite-sheets-in-responsive-sass
- https://css-tricks.com/forums/topic/responsive-sprites-using-compasssass/