Posted by & filed under Coding, css, Responsive Design, Tutorial, Website Design.

At one time or another, you may have found yourself wanting to use sprites in your responsive website design. While at first this may seem like a very simple task, in reality it’s a little more difficult of a challenge. It can, however, be done. Here’s how! This trick is fully supported by all modern browsers other than IE 8 and earlier, in which the image resizing aspect will not work properly, though it will not break completely.

Let’s start with our HTML. Let’s say we have part of a website here, and what we want is for the background image of this div to change when we hover over it. The catch is that we are using a sprite for it (a single image containing both our normal and rollover images) and it’s a responsive design. Let’s take a look.

<div class="sprite"></div>

Truly groundbreaking.

Okay, the html isn’t really that relevant I realize now. I could make it more fancy to try to make it a “real world example,” but why bother? Keep it simple, stupid.

The secret is clearly all in the css. Let’s say this div is always a square,  using our trick to maintain the same aspect ratio for an element in a responsive design. This might be the CSS of the element before we’ve added the background image.

div.sprite {
width: 20%;
height: 0;
padding-bottom: 20%;
}

Now we have a square image we want to nestle nicely inside there. And when we rollover the element, we want it to change. How do we do that? By adding the following css:

div.sprite {
width: 20%;
height: 0;
padding-bottom: 20%;
background-image: url("images/ourimage.png");
background-position: 0 0;
background-size: 200%;
display:block;
}

Now here’s what’s really interesting about the background-size property. It does not STRETCH the image in both directions, it assumes that the image fits perfectly WIDTH-wise into our container, and then calls that 100%. If we want the image to be larger than what actually fits in the container, we go bigger. If we want it to be smaller and have to repeat, we go smaller. In our case, let’s say our image is 1000px wide and 500px tall. On the left 500px we have the first image, on the right 500px we have the rollover image. If we were to leave the setting at background-size: 100%;, we would end up with the image fitting completely within the div and repeating itself once underneath.

We don’t want this, however. We want the first half of the image only to fit. So we set background-size: 200%;, since we need it to be twice as large as the space we have assigned for it, since we only want the first half of the image to fit in our div.

Now it’s time to set everything up for the hover state. To do that, we add this to our css:

div.sprite:hover {
background-position: 100% 0; /* Use ONLY percents here */
}

The only thing we need to change is the background position! The secret is to place the background image using only percents. This is what allows it to be responsive. Actually USING this positioning system can be a little confusing, so let me break it down for you.  The original location is at 0%. The position in which the image is as far over as it can go is 100%. This seems intuitive, but it can be confusing.

Consider the following example. You have FOUR images in one sprite that you wish to use, all in a row. You want to display the SECOND image in the row. What background position do you use? If you said  background-position: 25% 0; You would be WRONG! It’s actually background-position: 33.33333333333% 0;. The reason being because it is located only one-third of the the total distance the whole thing can actually slide. You can see how this would be confusing.

If you would like to see a real-life and real-creepy example I made using my own face, check it out here!

Brian Johnson

Brian Johnson is a website developer and designer living in Lakeville, Minnesota with a passion for code and WordPress. He spends his days building WordPress websites for small businesses, developing new code with the online community, and living life. If you have a question for him, you can tweet him @brianjonline or email him at brian@brianjohnsondesign.com.

More Posts - Website

Follow Me:
TwitterLinkedInGoogle PlusYouTube

37 Responses to “How to Use Responsive Background Image Sprites – CSS Tutorial”

  1. Krzysiek

    Hi Brian ,
    Thanks, this helped me a lot. But one thing bothered me – somethies I need use max-width and min-width to my image.

    I found way to do this and I just want to share it with You:

    .sprite_container{
    width: 30%;
    max-width: 400px;
    min-width: 200px;
    }
    .sprite{
    width: 100%;
    padding-bottom: 45%;
    background: URL(‘sprite.jpg’);
    background-size: 200%;
    background-position: 100% 0%;
    }

    One thing to mention:
    padding-bottom of ‘sprite’ div is proportion of single image(not whole sprite) width to single image height, so:

    .sprite {
    padding-bottom: (image.width/image.height) %;
    }

    Let me know what You think about it,

    Reply
  2. Jay Mueller

    HI Brian. Thanks for the tutorial. I’ve been looking at several sites for responsive sprites and yours was the easiest to follow. However, I can’t seem to get my head around the CSS needed for say, two different people side by side with alternate images beneath and hovering over would only change the image of the face you hover over. I made your sprite work vertically but not vertically and individually. I assume I would need to set up an unordered list to do it but haven’t been able to come up with the right CSS.

    Reply
  3. Melissa

    Hello Brian, I am having trouble positioning my responsive sprite. I am sort of a beginner so it might be something really simple that I’m not recognizing. I want to maintain the same aspect ratio to the top and left of my browser window. Right now when my height is adjusted the sprite moves from my intended spot. I tried adding padding-top to the css but that did not work. Thanks for any help or advice you have.

    Reply
  4. Brian

    This is the first article that I’ve seen on responsive sprites. I thought it was possible, but now I know its possible. #GoodStuff

    Reply
  5. Katherine

    Hi and thank you for the nice tutorial. There is not much for this topic when I google as I have been doing for a few days now. I think your tutorial comes up directly or is referenced in about a third of the search results. I have a question, though, if I may:

    I have plugged the code in and altered the shape a bit for my image and that works perfectly, but what I want to do with it is make a menu with a unique sprite for each item. I’ve made such in the past, but it was not responsive and, though I have tried to make this technique work by plugging it into ul/li properties, I have been failing miserably. Can this be made into a menu and, if so, what would the css look like?

    Reply
  6. Josh Carroll

    Brian, first off this is some great stuff! Very helpful post. The main issue that Im having with this is image wobble for cross-browser support. I feel confident that I’ve done the math correctly, but I assume that at different resolutions, different browsers are treating the % shifts by either rounding the pixel value up or down (creating the wobble). How have you dealt with this in your implementations?

    You can see an example here: http://151atbiscayne.com/floor-plans-alt/
    It works wonderfully in Chrome (which handles sub-pixel values) at almost all resolutions, but seeing issues in Safari, some FF and IE9+. Any advice you might have would be appreciated!

    Reply
    • Brian Johnson

      It looked like it was working fine to me! The browsers seemed to work differently in terms of how they resized things live during browser resizing, but seemed pretty consistent while the browser size was static.

      Reply
  7. travis simpson

    This is an awesome solution, thanks so much Brian! One item I am troubleshooting, when I use this sprite method my image is ever so slightly blurry. Any clue what this might be?

    Reply
    • Brian Johnson

      Make sure the actual image size is the exact correct dimensions. If it’s even a pixel off, it will display blurry. I recommend inspecting the image element in your browser and verify what size it’s actually displaying at, and comparing that to the actual image file.

      Reply
  8. M One

    After an hour of playing with this conclude that it doesn’t work for me. Using a single large icon sprite (250×250) and the pixel shift on rollover is beyond acceptable parameters with IE and FF. Cannot test with your demo as the image changes entirely – might be useful to post a demo with a simple rollover icon color change so can test properly. But for now I’m back to square 1.

    Reply
    • M One

      at 40% the shift is in your face – at 36% it’s barely noticeable. Something to do with math I guess ;)

      Reply
        • Brian Johnson

          If you are getting any kind of shift, odds are you are not doing the math correctly. You need to be exact. Depending on what you are attempting, it’s entirely possible you need to be getting down to the fraction of a percent. Again, the shift itself is hard to wrap your head around, you may be doing it incorrectly. Perhaps share your code on a js fiddle so I can see what you are dealing with and how to fix it.

          Reply
  9. Hannah

    I’ve been looking for days for a solution to responsive sites with css sprites. Thank you for coming up with a great solution! SO helpful.

    Reply
  10. Joe

    Unrelated but interesting to note:
    I think using background-size: cover; works the same as 100% 200%; etc. it stretches the image till the div is filled and leaves out whatever is left (the other half of the sprite). It worked fine for my 16-part sprite if I’m not mistaken.

    Reply
  11. Joe

    I have the same problem as the previous 3 coments…on FireFox on Mac/Linux… a slight shift and it even shows a sub-pixel black or grey border on one or two sides of ‘some’ of the divs. I have a 16-part sprite with 8 responsive divs and rollover. FF is the only browser that remembers the sub-pixel amounts after the decimal (like .666%) in case the div relies on one to its left….it adds them together when needed. My divs are often 80.2444px wide by 40.2482px high and those extra bit get a shade applied to them somehow! Bummer. Might have to split the sprite into 8 sprites and try the simpler approach.

    Reply
  12. Stokkolm

    This is a simple and effective implementation, yet it has the same problem as the other “responsive sprites” implementations I’ve encountered.

    The problem is non-chrome browsers will render a fraction of pixel from the next image. When you only have few images in a sprite and they both have same background this won’t be noticed, but when you have 20 images, the background will be wrong with a 20 times that fraction of a pixel, anywhere from 0 to 19.999px.

    I think the bug appears because most browsers round the sizes of elements to integers, but still use the raw number for percentage calculations. Chrome is the only one that works fine in this regard.

    I don’t know any fix for this, but I wish I did.

    Reply
    • Tom

      Thanks for posting this. I just found out about this rounding issue on the MozillaZine forums.

      Reply
  13. Tom

    Thanks for posting this article! It provided just the missing piece to a puzzle I’m currently working on. :)

    One question: during my testing, I’ve found in Firefox 25 (on Linux) one of the background changes causes a noticable “shift” in the background image. This doesn’t happen in Chrome 31, on the same system.

    My sprite is a JPEG image, 600×400 in dimension. I have four images in it, with each “normal” and “hover image in a row.

    The first row of images display and behave just fine in both Firefox and Chrome. The second row of images causes the “shift” behavior in Firefox that doesn’t appear in Chrome.

    Would you have any remote idea as to why this might be happening? The issue is a lot worse in Opera 12, but considering Opera 12 is pretty much dead, I won’t worry about it too much. At least not until I get the Firefox issue resolved. :)

    Thanks in advance!

    Peace…

    Reply
  14. Jeremie

    AWESOME! Everywhere else they said it couldn’t be done, or they had some javascript answer that may or may not work. This is an amazing solution! Thank You. My only other wish would be for Microsoft to give up on making browsers!

    Reply
  15. Ryan Neudorf

    Thanks for this great article.

    Everything up until the last paragraph was really helpful. But I had to do quite a bit of fiddling around until I understood exactly how images wider than 2 columns work. Unfortunately, I’m not entirely sure how to put it into words.

    Reply
  16. Anir

    hmmmmm I dont get it, I think I need to learn some part
    before this one. Thanks for Sharing, gonna bookmark this page
    so that I know were to find this.

    Reply
  17. Joe Conlin

    Wanted to check to see if you have heard of any Way to also support IE8. Would love to start using this but still have to support IE8.

    Reply
  18. Rick

    +1 on the positioning comment. It was the only piece of the puzzle I was missing, and it totally saved my bacon. Thanks!

    Reply
  19. Seth

    Thanks for posting this. It saved me a bunch of time this morning. Nice one.

    Reply
  20. Dave

    This is freaking awesome, so hard to find anything useful for responsive sprites – thank you.

    Reply
    • Brian Johnson

      No problem! And I agree, it’s hard to find good resources about it. Glad I could help! Let me know if you have any other questions and I’ll do my best to answer.

      Reply
  21. Piyush

    Hey can you post a tutorial about responsive navbars using image sprites and css.?
    Thank you.

    Reply

Trackbacks/Pingbacks

  1.  How to Make CSS Image Sprites Responsive | Netmajic Social Media

Leave a Reply

  • (will not be published)