Heading image for post: Using a Matrix to Generate Sprite Map SASS


Using a Matrix to Generate Sprite Map SASS

Profile picture of Shane Riley

I'd like to show you a SASS technique that I've been waiting to implement myself first in a client project, but so far have been unable to. I cannot wait any longer; I must share this awesomeness with all of you!

Let's say you have an image sprite of country flags that will be used to display which locale your internationalized site is currently in. Your designer hands you a sprite map all made up, but this time it's different. Instead of each flag being laid out in one row or column for you to easily iterate over like we learned in a previous blog post, we have rows of 5 flags each. You may be shouting "FFFFUUUU" at this point while thinking how much trouble it's going to be to recut this sprite map as a single row or column in order to use your awesome SASS trick. There is a way to work with it as is, however.

For this solution to work, we need to employ a new control directive and built-in SASS function. We're going to use the @for loop rather than an each loop to run from 0 to the length of each direction in our flag matrix. We'll then use a SASS function called nth that will let you pull the nth element in an array in SASS.

To start, let's create our styles for an individual flag. We're using a subset of the Famfamfam flag set as a sprite sheet, so we're going to style our anchors based on their dimensions.

  overflow: hidden
  width: 90px
    float: left
    padding: 0 2px 2px 0
    display: block
    width: 16px
    height: 11px
    text-indent: -8685px
    overflow: hidden
    background: transparent url("/images/famfamfam_flag_icons/example.png") 0 0 no-repeat

Nothing too fancy. We're using an image replacement technique to give dimensions to the anchor and hide the text within it in favor of the icon background. In the HAML I'm creating these links with a title attribute that tells me which country each flag is from.

- @flags = { ca: "Canada", cn: "China", de: "Germany", uk: "England", es: "Spain", fr: "France", it: "Italy", nl: "Netherlands", se: "Sweden", us: "United States of America" }

%h1 Country Flag Sprite Matrix
  - @flags.map do |cc, name|
    %li= link_to name, "#", class: cc, title: name

Next, we're going to define our rows and columns based on the class names we've given each flag. In SASS we would define our rows in variables, then define our matrix using those rows. SASS will allow you to skip the comma separators in these declarations, but they read and scan much easier with them.

$row_1: ca, cn, de, uk, es
$row_2: fr, it, nl, se, us
$flags: $row_1, $row_2

We'll then iterate over the flags matrix with two for loops. There are two keywords, to and through, that you use when defining a for loop in SASS. through is inclusive, meaning it will go up to and including the last value in the range. We're going to use to for the purpose of setting the x and y positions of our background.

    background: transparent url("/images/famfamfam_flag_icons/example.png") 0 0 no-repeat
    @for $y from 0 to length($flags)
      @for $x from 0 to length(nth($flags, $y + 1))
        &.#{nth(nth($flags, $y + 1), $x + 1)}
          background-position: (-$x * 16px) (-$y * 11px)

In the first for loop, we'll run from 0 to the number of rows read from calling the length function and passing the $flags matrix. We then start a for loop to iterate over that row's elements up to its length. A little bit of calculation based on the width and height of the icon, and we've got a properly positioned background image for each country code. Check out the example page.

When time permits, I'll create a version of this demo with the entire flag set loaded in for anyone that needs it. Follow me to find out where you can get it at when I'm done. In the meantime, get going on those sprite matrices!

More posts about CSS Design