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).
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.
I just noticed the facebook uses this method to round corners on their thumbnails the other day.
Great tutorial.
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.
Great article, useful stuff. :) I love CSS.
IMG is not proper element for icons i think.
Arguably true.
However, I can think of a number of ways to use this anyway. I’ve never heard of it before, so thanks for a great article.
I can think of a number of ways to misuse this. It’s probably not been heard of been heard of before because there are generally more relevant ways of accomplishing it.
Wow, I love not proofreading my posts.
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.
This is a great technique to master, thanks for the resource Chris.
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 withclip()
. 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!
It would be nice if that Anything Slider worked off of 1 image like this approach.
The “Top Right Bottom Left” goes clockwise, rather than following a rectangle. You can go either way on a rectangle.
I learned the acronym TRouBLe as well as the clockwise trick – might help folks who learn that way :)
I never heard that before but it’s a nice trick!
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!
You’re blog continues to kick ass.
Quality content for novice developers like me.
Thanks for not sucking.
Neat little trick and good to know that it works in all major browsers. I am going it try it in my next project.
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.
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 :)
It’s 2009, if you have CSS turned off you have bigger problems. Any browser (even mobile) worth mentioning has CSS support.
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.
RSS Reader. It turns off CSS.
Gotta love tables… :D
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.
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!
helou, try add some png transparency fix for IE.
btw nice tut.
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.
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.
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.
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!
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
Good point. If you are using the wrapper technique, this is a good way to go.
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*)
cool! just yesterday I had to cut image like this becouse I didn’t know about clip. today I’ll do it this way
“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.
Nice work. It’s always good to see sprites in action and nice to see a slightly different angle.
Très intéressant ! Il peut rendre service dans beaucoup de cas de figure ! Merci ;)
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.
Chris, le CSS c’est toi! I had never heard before about a property called “clip”.
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.
Hats off Chris ! Awesome discovery … it would reduce tons of httprequests if used cleverly. Wow !
Using sprites cleverly also means taking care of the browser memory.
Nice! I seen this technique used in many area.
This is great! I didn’t even know you can do this!!!
不错的技术,Yahoo首页上的侧边栏也用到了,学习了!
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.
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
Chris this is good stuff – big relief to know it works in IE6.
This was an “Aha!” moment for me. Was playing about the other day wondering if this could be done. Thanks.
Very clever! great tutorial ;)
some days back i knew much about clip property and here you are with cool trick …. thnx for sharing …. nice article …
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.
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.
I just learned anew technique today ,thanks for sharing Chris
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.
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.
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.
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.
I appreciate that this article was written back in 2009 but I’m hoping I might find an answer to a query I have.
I have an image (250×250). I want to break this into 5, both ways (25 pieces). Rather than having a class for each position (.pos1, .pos2, … .pos24, .pos25) I was hoping to try and reduce the CSS by defining the CSS in columns and rows. This would mean I would only have to define 10 classes (.c1, .c2 … .c5 and .r1, .r2 … .r5), and then apply these classes to each img element to represent it’s location (class=”clip c1 r1″, class=”clip c1 r2″ etc.).
For columns I would specify the right and left values. For the rows I would specify the top and bottom values. I thought it was a brilliant idea. However, I quickly ran into a problem because the clip property specifies all edges (top, right, bottom, and left).
Is there anyway to omit one or more of the edges from the clip property? Otherwise, I may as well write a class definition for each position.