Sprite sheets images building for web solutions is an ancient technique, but web sites without any sprite sheet are ubiquitous. I think one of the reasons for that is missing knowledge about creating those. Today I would like to share with you how simple CSS sprite sheets may be.

We are going to use SCSS and Compass framework.

Compass Framework

The official compass documentation is here. What is the compass framework? It is a package of really useful mixins and methods which makes your frontend development process faster. For example, all you need to create a sprite sheet from a directory of images is that:

$icons: sprite-map('icons/*.png');

I’ll show you how to use that later in this article. There are two requirements: ruby and compass gem. You should install ruby first, and then you can install Compass like that:

gem install compass

Project structure

To make something -> we need a project. That would be our compass project structure for today:

Example compass project structure

- configs/_compass.scss

// just a list of compass imports
@import "compass/reset";
@import "compass/css3";
@import "compass/utilities";
@import "compass/support";

- configs/_sprites.scss

Sprites creation scripts, we will back to that later.

- modules/_icons.scss

Here we are going to create our CSS classes with sprites.

- app.scss

The entry point of our SCSS front-end project

// ### Configs ########################
@import "configs/compass";
@import "configs/sprites";

// ### Modules ########################
@import "modules/icons";

- config.rb

=begin
################################################################## 

  Compass project configuration
 
##################################################################   
=end

=begin
/*************************************************************************************
 * Dirs configuration
 *************************************************************************************/
=end
css_dir = "../styles"
sass_dir = "."
images_dir = "../styles/images"
sprite_load_path = "../assets/sprites"

=begin
/*************************************************************************************
 * HTTP pathes
 *************************************************************************************/
=end

# Root url
http_path = "/"

#
=begin
/*************************************************************************************
 * Other configuration
 *************************************************************************************/
=end

# :stand_alone or :rails
project_type      = :stand_alone 

# :production or :development
environment       = :development 

# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass

# To enable relative paths to assets via compass helper functions.
relative_assets = true

# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
# Choose your output style, :nested, :extended, :compact, :compressed
output_style = ( environment == :production ) ? :compressed : :expanded
# To call: compass compile -e production --force

# To disable debugging comments that display the original location of your selectors. Uncomment:
# Defaults to false in production mode, true in development mode.
line_comments = false

How may we run the project?

$ compass watch -c config.rb -s compressed

TIP - by default compass would compile each of .scss files to CSS file with the same name unless its name begins with _ underscore. It is a reason why some files have a name with _ at the beginning.

Create the sprite sheet

In case of our example, we are going to create icons sprite sheets. Two important things before we can start are: images_dir and sprite_load_path configuration variables. You should find them inside your config.rb file. The first one images_dir tells compass where it should store generated images the second one sprite_load_path tells where it should look for images.

Let’s go to the configs/_sprites.scss file and initialize icons sprite sheet:

$icons: sprite-map( "icons/*.png", $spacing: 2px, $layout: horizontal  )

If you would like to customize one of the images for example add no-repeat to some icon background property you need to put additional arguments to the sprite-map function. Let’s say you have icon image calls arrow.png

$icons: sprite-map( "icons/*.png", $spacing: 2px, $layout: horizontal,
                    $arrow-position: 100%, $arrow-spacing: 15px, $arrow-repeat: no-repeat)

Now we can use $icons inside our SCSS blocks.

Compass brings us a few functions/mixins to deal with sprite maps.


sprite($sprite_map, $icon_name)


It puts the background property with correct URL, background position and repeat values.

background: sprite($icons, 'my-icon');

Compiled css might looks like this:

background: url('images/icons-sf2b30443c4.png') -258px 0; 

sprite-dimension($sprite_map, $icon_name)


It puts width and height property

@include sprite-dimension($icons, 'my-icon');

Compiled css might looks like this:

height: 256px; width: 256px;

sprite-position($sprite_map, $icon_name, $offset_x=0, $offset_y=0)


It puts the sprite background position

background-position: sprite-position($icons, 'my-icon', 0, 0);

Compiled css might looks like this:

background-position: -258px 0;

Okay so now we can create our first sprite sheet packaged icon

.icon-my-icon {
  background: sprite($icons, 'my-icon');
  @include sprite-dimension($icons, 'my-icon');
  @include inline-block;
}

Mixins

Good point here is to create some helpers which allow us to use sprite sheets faster without copy&paste same code lines again and again. We can add them inside the configs/_sprites.scss file.

sprite-box-image

One of the most common usages of images in our application will be probably the creation of image boxes. We can create mixin which creates a box image using a given sprite sheet.

@mixin sprite-box-image( $spriteMap, $sprite ) {
  background: $spriteMap no-repeat;
  background-position: sprite-position($spriteMap, $sprite, 0px, 0px);
  display: inline-block;
  @include sprite-dimensions($spriteMap, $sprite);
}

Great! now we can use that mixin in an effortless way

.icon-my-icon {
  @include sprite-box-image($icons, 'my-icon');
}

Example compiled css:

.icon-my-icon {
  background: url('images/icons-sf2b30443c4.png') no-repeat;
  background-position: -258px 0;
  display: inline-block;
  height: 256px;
  width: 256px;
}

sprite-bg

The second usage which I have in mind is to add a background to the block. The following mixin helps us with that

@mixin sprite-bg( $spriteMap, $sprite ) {
  background: $spriteMap no-repeat;
  background-position: sprite-position($spriteMap, $sprite, 0px, 0px);
}

Simple example:

.block-with-background {
  @include sprite-bg($icons, 'my-icon');
}

Example compiled css:

.block-with-background {
  background: url('images/icons-sf2b30443c4.png') no-repeat;
  background-position: -258px 0;
}

Automatic generated classes

Compass gives us one great feature - generate CSS classes for given images folder automatically. Let’s say we have a directory with three images: img1.png, img2.png and img3.png. Now we would like to create a sprite sheet that contains those images and then create a class with an image setup for each image.

With compass it is straightforward, we are going to use the … sprites mixin.


sprites($sprite_map, $sprite_class_suffix)


We can use that mixin, but the faster way is to use @import keyword. Let’s say we’ve put following code inside modules/_icons.scss

@import "compass/utilities/sprites";
@import "icons/*.png";
$icons-sprite-base-class: '.icon';
$icons-sprite-dimensions: true;
.icon {
  @include inline-block;
}
@include all-icons-sprites;

Example of compiled CSS:

.icons-sprite {
  background-image: url('images/icons-s19bc0c3f12.png');
  background-repeat: no-repeat;
}

.icon, .icons-my-icon1, .icons-my-icon2 {
  display: inline-block;
  vertical-align: middle;
  *vertical-align: auto;
  *zoom: 1;
  *display: inline;
}

.icons-my-icon1 {
  background-position: 0 0;
  height: 256px;
  width: 256px;
}

.icons-my-icon2 {
  background-position: 0 -256px;
  height: 256px;
  width: 256px;
}

Example of usage in HTML

<html>
  <body>
    <div>
      Super icon: <i class="icons-sprite icons-my-icon1"></i>
    </div>
  </body>
</html>

There is one tricky case here - if you would like to change the prefix you are pushed to use sprite mixin without magic import. One disadvantage here is you need to put an array of images names as the second argument - not ‘all’ option here by default.

.icon {
  background: $icons no-repeat;
  @include inline-block;
}
@include sprites($icons, my-icon1 my-icon2, '.icon', true, 'icon');

Example of compiled CSS:

.icon, .icon-my-icon1, .icon-my-icon2 {
  background: url('images/icons-sf2b30443c4.png') no-repeat;
  display: inline-block;
  vertical-align: middle;
  *vertical-align: auto;
  *zoom: 1;
  *display: inline;
}

.icon-my-icon1{
  background-position: -258px 0;
  height: 256px;
  width: 256px;
}

.icon-my-icon2 {
  background-position: 0 0;
  height: 256px;
  width: 256px;
}

The last thing, usage in html:

<html>
  <body>
    <div>
      Icon 1: <i class="icon icon-my-icon1"></i>
    </div>
  </body>
</html>

Credits

I use Compass a lot, and it is one of my favourite CSS power-up solutions. I hope the sprites creation will be easy for you after this day :)

The official Compass sprites documentation can be found here: Compass sprites