Grow your CSS skills. Land your dream job.

CSS Sprites with Inline Images

Published by Chris Coyier

CSS Sprites is a technique where you use a background-image, a set width and height, and adjust the background-position to display only the portion you need to show. This way you can use a single image and display lots of different graphics with it, saving server requests and speeding up page load times.

The "sprite" is the single, combined graphic. We can use this same theory, only instead of using background-image to show the graphic, we can use an image right in the HTML itself (inline image).

 

View Demo

 

Why?

I don't know if I have a perfect answer. This is mostly just a proof of concept and demo of how to use the CSS clip property. Although, inline images are just inherently different than divs with backgrounds. The image is "content" while an empty div is not.

CSS Clip

The theory is to use the clip property of CSS to trim the image down to display only the section of it needed to show. Preparing the image would be the same as creating any other CSS sprite:

You display it with regular HTML, giving it a couple of class names we'll use:

<img src="images/arrow-sprite.png" alt="arrow" class="clip pos-1" />

In order to use CSS clip, the element must be absolute positioned, so we'll do that with the generic "clip" class, and apply some default/required top and left values. Then we'll set up a class name for each of the different images within the sprite. One position class name for each image:

.clip               { position: absolute; top: 0; left: 0; }
		
.pos-1              { clip:rect(0 48px 48px 0); }
.pos-2              { clip:rect(0 96px 48px 48px); left: -48px; }
.pos-3              { clip:rect(48px 48px 96px 0); top: -48px; }
.pos-4              { clip:rect(48px 96px 96px 48px); top: -48px; 
                      left: -48px; }

Notice the negative top and left values applied for the different positions. This is necessary to move the image back up to the standard position you would expect it to appear. However much of the image you chop away from the top and left, you scoot it back up and to the left that far. This is because the image will occupy the same space as the entire sprite, just have parts of it not appear. But thanks to absolute positioning, this extra space won't affect anything else and we can nudge it back into place without affecting anything else.

Each "position" follows a rectangle pattern in shorthand, just like margin or padding use in shorthand: Top, Right, Bottom, Left. Fair warning... this can feel a bit weird to write. It feels more natural to write Top, Left, Bottom, Right, like X,Y coordinates, but that's just not how this works.

It is a little limiting that it must use absolute positioning. If you want to keep your image as part of the regular flow of the document the best you can, you can always wrap the image in a div with relative positioning.

<div class="clipwrapper">
   <img src="images/arrow-sprite.png" alt="arrow" class="clip pos-1" />
</div>
.clipwrapper        { position: relative; height: 48px; width: 48px; }

Same Server Use

Browsers are smart enough to know that if the same image is used in more than one place on the page, it still only needs to load it once. Just as efficient as traditional CSS sprites. Look ma, just one resource:

Browser Compatibility

This works in IE 6, 7, and 8, plus all the good browsers I tried. That makes this absolutely usable all around.

NOTE: The CSS spec calls for commas between the values in the clip property, but apparently older IE doesn't like them and it works fine without them in newer browsers.

Comments

  1. Chad
    Permalink to comment#

    I just noticed the facebook uses this method to round corners on their thumbnails the other day.

    Great tutorial.

  2. Tom
    Permalink to comment#

    Oh, I didn’t even know this technique existed, let alone it works from IE6 upwards. I’m wondering though if there’s a situation where you need it?

    I, for my part use inline images only if it can be regarded as valuable content and mostly thats big photos or thumbnails. Combining them doesn’t make sense, you will loose that content then.

    Inserting images for rounded corners? Maybe if you need to create boxes which need to resize vertically as well as horizontally, else sprites.

  3. Great article, useful stuff. :) I love CSS.

  4. IMG is not proper element for icons i think.

  5. Sprites reduce load time by keeping HTTP requests to a minimum. One file with a few extra pixels uses fewer server resources than many individual files. Plus, since the entire file loads at once, transitions are snappy — the site won’t hesitate when a visitor mouses over over an element, waiting for the hover state to download.

    Of course, all the sprites must use the same color palette, but a little consistency doesn’t hurt.

  6. Permalink to comment#

    This is a great technique to master, thanks for the resource Chris.

  7. Casper
    Permalink to comment#

    On point as always, Chris!

    I’ve been using this technique on a site-about-to-launch recently, where I had no control over format/size of images in posts. (Import from Joomla to WP, new posts are no prob.)

    I scale the images down with width + height, and then keep ‘em in place behind a transparent PNG overlay with clip(). Works like a charm, although some of the images are really big and causes unnecessary loading for now – it’s just for a short period, tho.

    Cheers!

  8. Mike
    Permalink to comment#

    It would be nice if that Anything Slider worked off of 1 image like this approach.

  9. Ash
    Permalink to comment#

    The “Top Right Bottom Left” goes clockwise, rather than following a rectangle. You can go either way on a rectangle.

  10. Bart
    Permalink to comment#

    Hi,

    I think you should use comma’s in your rect brackets to seperate the values or you will encounter validation errors…

    Great little technique though!

  11. Permalink to comment#

    You’re blog continues to kick ass.

    Quality content for novice developers like me.

    Thanks for not sucking.

  12. Neat little trick and good to know that it works in all major browsers. I am going it try it in my next project.

  13. Permalink to comment#

    I actually thought about doing this when I first heard about the clip property, but the more I think about it, the more I don’t get why I would want to use this. If the image is content, then only one of the sprite image would make sense in the context. If CSS is turned off, then you lose the meaning of the image, since it will show all the other images in the sprite.

    • Gappa
      Permalink to comment#

      Totally agree – this was the first thing that crossed my mind when I saw this approach.

      Turn off CSS and your site will turn into a complete mess with lots of same pictures showing multiple actions on different places.

      The visual effect is ok, but the content is the one being hurt here :)

    • Jqueryin
      Permalink to comment#

      It’s 2009, if you have CSS turned off you have bigger problems. Any browser (even mobile) worth mentioning has CSS support.

    • Permalink to comment#

      why the heck would anyone want to turn OFF CSS? except maybe for quick checking the tidiness of HTML, nothing comes on my mind…

    • I tend to agree with everyone else: Who would turn off CSS? Without CSS, we would still be building sites with tables.

      The only people I can think of who would turn it off are developers who are trying to figure out how a site was constructed, and they are all smart enough to figure out what is what.

      This is a great tool and one I plan to implement in the near future.

    • AT
      Permalink to comment#

      RSS Reader. It turns off CSS.

    • Permalink to comment#

      Gotta love tables… :D

  14. Thanks for the write up. Im currently displaying the footer images on my site this way because I didn’t want to show them load individually.

  15. Thanks for this! Even though it was inline specific, it’s one of the better explanations of CSS sprites and clip() that I’ve read to date. Great stuff!

  16. |Walter|
    Permalink to comment#

    helou, try add some png transparency fix for IE.
    btw nice tut.

  17. karl
    Permalink to comment#

    worth noticing here is that the syntax documented in CSS specs is clip: rect( 10px, 10px, 10px, 10px);

    but this doesn’t work in IE6, in IE6 you have to leave out the , delimiter.

    • Permalink to comment#

      Confirmed! I was just coming here to mention this tip. It is not just IE6 either. In general IE ignores the recommended comma delimited syntax, yet recognizes the optional space delimited value.

      I’ve got to wonder how many other IE compatibility issues I’ve hit relate back to this…

      I use the clip command to trim the black lines from the top and bottom of thumbnails for widescreen YouTube videos.

  18. Permalink to comment#

    Works – YES, is valid use of html – NO. By html standard every image (element) should be usable without css (visual extension of markup) – so the image without clipping is completely useless, for example for people in need of accessibility. So instead of clipping use a placeholder transparent gif and use sprite as its background – so when falling back to html only mode it doesn’t destroy everything.

  19. Ended up with a great use for this. I need graphic button in different languages. This way I can swap out to correct language without having to store multiple graphics in a database table.

    Thanks!

  20. Chris
    Permalink to comment#

    You can just add overflow:hidden; to the clipwrapper then remove the clip CSS completely (leaving the top and left) and it will work just the same ;)

    ~ Chris

  21. LuK
    Permalink to comment#

    And again learned something new!! Great tutorial and somehow a nice “uncovering” of CSS tricks…never heared of the clip property^^…(shame on me and everybody else *g*)

  22. Permalink to comment#

    cool! just yesterday I had to cut image like this becouse I didn’t know about clip. today I’ll do it this way

  23. Permalink to comment#

    “NOTE: The CSS spec calls for commas between the values in the clip property, but apparently older IE doesn’t like them and it works fine without them in newer browsers.”

    So it turns out that it’s badly implemented in good browsers then.

  24. Nice work. It’s always good to see sprites in action and nice to see a slightly different angle.

  25. Très intéressant ! Il peut rendre service dans beaucoup de cas de figure ! Merci ;)

  26. Permalink to comment#

    I think this inline-sprite-technique is useless.
    Using a span with negativ indent for text-image-replacement and sprites is one tag with the same effect. Also if you use an anchor, only one tag.
    In this technique you allways need to tags and if css is turned off – say hello to all this nice sprites.

  27. Helen
    Permalink to comment#

    Chris, le CSS c’est toi! I had never heard before about a property called “clip”.

  28. Neil
    Permalink to comment#

    A good tutorial on clip (it can also be used to change background and foreground colours within a div), but unless it is as simple as four arrows you are going to struggle with accessible alt attributes.

  29. Hats off Chris ! Awesome discovery … it would reduce tons of httprequests if used cleverly. Wow !

    • Helen
      Permalink to comment#

      Using sprites cleverly also means taking care of the browser memory.

  30. Permalink to comment#

    Nice! I seen this technique used in many area.

  31. This is great! I didn’t even know you can do this!!!

  32. Permalink to comment#

    不错的技术,Yahoo首页上的侧边栏也用到了,学习了!

  33. Permalink to comment#

    Good Article! But when checked with the css validator (jigsaw.w3.org) it gives 4 errors as follows:

    .pos-1 – Value Error : clip Invalid separator in shape definition. It must be a comma. : rect(0 48px 48px 0)

    .pos-2 – Value Error : clip Invalid separator in shape definition. It must be a comma. : rect(0 96px 48px 48px)

    .pos-3 – Value Error : clip Invalid separator in shape definition. It must be a comma. : rect(48px 48px 96px 0)

    .pos-4 – Value Error : clip Invalid separator in shape definition. It must be a comma. : rect(48px 96px 96px 48px)

    Please help to get the solution.

  34. Nice, thanks!
    Another way is to use a 1x1px transparent img and apply a class to it to make the sprite

    see here: http://cssglobe.com/post/3028/creating-easy-and-useful-css-sprites

  35. Chris this is good stuff – big relief to know it works in IE6.

  36. Permalink to comment#

    This was an “Aha!” moment for me. Was playing about the other day wondering if this could be done. Thanks.

  37. Very clever! great tutorial ;)

  38. some days back i knew much about clip property and here you are with cool trick …. thnx for sharing …. nice article …

  39. Permalink to comment#

    Interesting have never heard of clip before, this technique does seem useless though you can avoid the clip altogether and just do overflow: hidden; on the container. Exactly the same result.

  40. Not a good technique for sprites.
    It fails to separate content from style.

    Consider what happens when style sheets are not supported or are unavailable.

    A good tutorial on the usage of the clip property though.

  41. I just learned anew technique today ,thanks for sharing Chris

  42. Permalink to comment#

    I dont like using css sprites. They are too complex for me. Also computing them is a hell of task for me. Bandwidth limits are decreasing day by day and we are getting faster connections. I would like to have four 5kb images rather than single 5kb image with lots of coding.
    Regards.

  43. rgraham
    Permalink to comment#

    Great post. I’m glad i found this i was having a hell of a time getting the css sprites with background positioning, png’s and IE 6 to work.

  44. Permalink to comment#

    There is an automated tool to create CSS Sprites – inside Web Optimizer ( http://code.google.com/p/web-optimizator/ ). It supports all known cases and issues of background images usage.

  45. Permalink to comment#

    You raised the question about why one would use this over background-image, and I do have one answer: using images inline fits accessibility standards for those who have to use screen-readers; background-images can’t have alt text and are often completely hidden with high-contrast or other compromised-vision modes. Semantically it just makes sense. Even tricks like text-indent:-9999px or the usual hacks won’t work with high-contrast or other modes, so inline sprite maps have that going for them.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".