CSS Sprites w/out Using Background Images
Tags: Beginner
Recently I was working on a client site and he wanted a hover effect on some of the affiliate banner ads. The first approach in my mind was to do the typical CSS Sprites but this requires CSS work which my client did not know much of. I wanted to give him the access to update his affiliate banners using WordPress, and the simplest thing was to let him just upload his own images and put the URL in a custom field. No CSS tweaks involved, just what he needed.
What’s the Downside of CSS Sprites?
For this situation, there were a couple issues that I was not comfortable with:
- CSS Sprites requires basic CSS Knowledge. I didn’t want the client going in and potentially breaking his own site.
- The more affiliate banners, the more class names you will need to create. If we had 20 banners, we will have 20 unique class names. Being the picky front-end ninja that I am, this didn’t sit well with me.
Try the Demo
As you can see below, these are not background images. Just your typical <img /> tag that has been masked with a little bit of CSS.
The Solution
If you really think about it, this technique is very simple and can be quickly achieved. Lets take a look.
HTML
We keep the markup nice and simple by only using the elements that we need. We use the <a> as the mask, and have our <img /> tag the one that shifts from one state to another.
<div class="affiliates">
<a href="#"><img src="rokkan.gif" alt="" /></a>
<a href="#"><img src="1md.gif" alt="" /></a>
<a href="#"><img src="designcubicle.gif" alt="" /></a>
</div>
CSS
Similar to how the regular CSS Sprites work, we specify the exact width and height of our sprite dimensions. Adding an overflow: hidden; allows us to achieve the masking effect by hiding anything that spills out of its specified boundaries.
To show the hover state, we simply add a negative top margin of the same height as the visible sprite area. Take a look at the height and margin-top in the code below.
.affiliates a {
width: 204px; height:182px;
overflow: hidden;
float: left;
}
.affiliates img {
border: none;
}
.affiliates a:hover img {
margin-top: -182px;
}
Extra Step – CSS3 Transitions
Lets take this a step further and have some fun with the new hot topic: CSS3!
Try the CSS3 Demo
*Note that CSS3 Transitions only work for Chrome, Safari, and Opera at this time. It will be available for Firefox when version 4 is released. Learn more.
HTML
Same markup as above! Don’t change a thing.
<div class="affiliates">
<a href="#"><img src="rokkan.gif" alt="" /></a>
<a href="#"><img src="1md.gif" alt="" /></a>
<a href="#"><img src="designcubicle.gif" alt="" /></a>
</div>
CSS3
Take our existing CSS and add the following lines in red. Notice that the default image has a margin: 0; and when hovered the margin-top: -182px; is applied. When applying CSS3 transitions, it will determine its animations from its default state to its hovered state.
.affiliates a {
width: 204px; height:182px;
overflow: hidden;
float: left;
}
.affiliates img {
border: none;
margin: 0;
-webkit-transition: all 0.2s ease-in-out;
-moz-transition: all 0.2s ease-in-out;
-o-transition: all 0.2s ease-in-out;
}
.affiliates a:hover img {
margin-top: -182px;
}
Browser Support?
CSS3 Transitions only work for Chrome, Safari, and Opera at this time. It will be available for Firefox when version 4 is released. Learn more.

How Does it Work?
Here is a breakdown of the transitions. Take a look at the links below for further explanations on each browser specific properties.

Related Articles
Image Based Sprites & Image Replacements
- iIR: img Image Replacement
- Foreground Sprites
- Image Replacement technique and the sprite method
- CSS Sprites with Inline Images
- Changing html images on hover/a quick css trick
- Mapped images and CSS Sprites
- Extending CSS Spriting
Sprites – High Contrast Mode Optimization
- Single-pixel
Replacement
- Using Sprite Images with Input Button for a Hover Effect
CSS3 Transitions
- Using CSS3 Transitions, Transforms and Animation
- Going Nuts with CSS Transitions
- CSS Three — Connecting The Dots
Related Posts
Author Bio
My name is Soh Tanaka and I am a Los Angeles based designer/front-end developer specializing in CSS driven web design with an emphasis on usability and search engine optimization. I also run a CSS Gallery which is updated daily with the best CSS websites from around the world. Come check it out!
You can learn more about me or
Follow me on twitter for more updates and resources!
Did You Enjoy This Post?
Subscribe via RSS or by email to get all upcoming tutorials and articles delivered straight to you.






+ Add Comment64 Peeps Have Spoken Their Minds...
Nice technique, cheers
You’re a wizard Soh! Love it!
A quick question on a completely different topic. Where would one start in creating custom WordPress themes? I have enough HTML & CSS skill to design, cut and code a site but would love to start utilizing the power of WordPress but just don’t know where to start. Books, online tutorials, course???
Cheers from Australia!
i Always Read your Tutorial. They Are Really Useful Keep It Up…..
Hey Soh… Nice tip. I liked so much the simplicity of it and much more because it works really fine on IE, I know IE doesn’t support transition, but the user will see the other part of image. :)
Just one warning, always remember to put the default css syntax, in this case: transition: all 0.2s ease-in-out;
Cheers,
@juarezpaf
Brilliant Tip. Thanks for tut. I saw that you have put up ads on website. I hope that you will be able to dedicate more time to SohTanka Now.:) Make sure you write awesome stuff for all the beginners.:)
At first I don’t understand when you say without background images. But then I realize you mean background images IN the CSS file, which me you just simply put the image with the tag. Cheers mate. Nicely done. Poor thing bout Firefox thou. Hope FF4 quickly release!
This is good stuff. On another topic, have you written a post about how you do your side navigation with the social networking links / comments on the left side which scroll with the page and then fix at the top?
Great and simple technique. I wasn’t aware that you could apply CSS3 transitions to this – that’s a real bonus :) Is it possible to apply a jQuery transition to the image on hover instead of/as well as CSS3? That would give some really cool effects.
Very clever and a great way to reduce the number of classes required.
Very Clever simulation and with css3 you just made it look so neat.
SOH, i,m ur SUPERFAN and u’re a GENIUS
Very helpful tut, thanks…
And in response to Timmy’s question about customizing WordPress, I’d suggest both the book and website (www.digwp.com) Digging into WordPress by Chris Coyier and Jeff Starr as a great place to start. I went from no WP knowledge to building completely customized sites and themes pretty quickly.
Like your article. Using sprites for a while now and I’d found this method fantastic. Didn’t know / use web transitions CSS3. Niceee :)
this is really very interesting and creative.
Could it be used for navigation rollovers and logos, I suppose.
I’ve been wanting to avoid the negative text-indent, and this gives an elegant solution
thanks
Cool! I just used CSS Sprites on a site. Your tutorials are very well written. This rocks! I can’t wait to dig in and try out this tutorial. Thanks for sharing the knowledge.
with css3 we can make more creatifity…
thanks for tutor
using css code on the existing first, any widening in hover effect
css code of the two, perfect is clear
nice i see i see
A little correction,
I am using FF 3.5 and its still working for me, but you have mentioned that it will start working with 4.
Anyways, thats a hell useful property. CSS3 rocks. I will try to use the same method in my blog Gtricks header logo.
I suppose a nice transition on header logo will look beautiful.
LOVE IT! CSS3 is gonna save us from a lot of JavaScript headache!
Wow! I really can’t believe someone didn’t think of this before – it’s so simple and yet so brilliant :) Great tut and amazing concept – keep up the good work!
@Timmy – I found Jeffrey Way’s tutorial @ NetTuts to be invaluable: http://net.tutsplus.com/articles/news/the-best-psd-to-html-to-wordpress-video-series-available-new-plus-tutorial/
@Soh – This article is just brilliant! I’ve not ventured into CSS Sprites yet, so it’s nice to know this can be done as effectively (and with awesome transitions) with plain markup. Thanks once again for an awesome tutorial (and sorry for linking off-site)
man, you make it look sooooo easy! great coding as always. thanks a lot!!!
Nice technique but… what about Graceful Degradation & Progressive Enhancement ?
Nice but it actually doesn’t have anything to do with CSS sprites. The main trick about sprites is that you keep *all* images in one image file and you move the file with background-position to only show the part you want to show: http://css-tricks.com/css-sprites/. This means that instead of loading 20 pictures you load one and your pages load much faster. It also means that they don’t pop up one after another. Your technique has no extra value for performance at all and doesn’t use the main trick of CSS sprites.
Hi Soh
I found this to be over complicating things a lot and then there is also the fact that this doesn’t working in Internet Explorer 6.
I think a better approach would be to use the old CSS sprites method and then simply adding a small piece of inline styling to each anchor e.g.
…
Then you can insert the “rokkan.gif” using the CMS (WordPress) instead of adding it to the IMG tag.
Problem solved :)
Hi Soh
I found this to be over complicating things a lot and then there is also the fact that this doesn’t working in Internet Explorer 6.
I think a better approach would be to use the old CSS sprites method and then simply adding a small piece of inline styling to each anchor e.g.
Then you can insert the “rokkan.gif” using the CMS (WordPress) instead of adding it to the IMG tag.
Problem solved :)
yes ….thats way cool…thank you for that in depth explanation !
greatly appreciated!
snapone
Very creative solution to the problem, although of course now the client will have to use an image editor to double up their images.
I think you should make it clear though that people shouldn’t use this as a replacement for using background images, as the solution here is very specific. Having to use a container with an overflow makes development a little trickier.
That’s awesome- way to improve on the css sprite technique on multiple fronts!
@ApolloNet Graceful Degradation & Progressive Enhancement? Works like a charm for modern browser and degrades fine and still accessible for older browsers :-)
@Chris Thanks for dropping by :-) Wouldn’t you agree that if you want to get technical, you can put all 20 images on one image and still use the same technique and make it work (would have to add some sort of left margin on each individual image of course which kind of defeats the simplicity of this tutorial). CSS Sprites as we both know has no limitations or rules on how we have to put ALL images on one image. The only difference I can see technically from this technique and the real sprites is that one uses a background image and this uses and actual image. But I developed this with the core concept in mind. I understand less server calls to images makes the performance better which is a major characteristics of sprites, bu I feel it is also a preference to the developer how he/she wants to utilize the technique.
I also feel that semantically, by having columns/rows of thumbnail style images, it would make more sense in the markup if they were actual images and not empty divs with background images.
Would love to hear your thoughts on this :-)
@Gerhard I didn’t think this was complicated at all, pretty straight forward don’t you think? The inline style route is also possible so I see your point, but I feel this technique still has some importance to it and just an alternative solution.
@Russell Bishop In order to make Sprite Images you will need an image editor either way. Can’t really move around that problem there. Regarding an explanation, I wrote a nice long introduction with bullet points explaining why this alternate method was used.
@SOH
You’re right, I think Christian is missing the big picture.
As my “CSS sprite with a twist” article shows, one can use a sprite as the SRC value of a IMG element:
http://tjkdesign.com/articles/how-to_use_sprites_with_my_Image_Replacement_technique.asp
@SOH yeah I agree that the concept can be used like normal CSS sprites but it still means that the client needs to create the images in the right format.
What this technique does better is that you will have alternative text for the images when you use them as navigation.
Have you looked at sprite-me? If you can script that as a process of a build script you can easily use whatever you want and create CSS sprites easily – http://spriteme.org/.
@thierry I am not missing the big picture, I am pointing out that the demo as it stands is not giving the same benefits as CSS sprites do. Having one image for all three links would show both benefits. When I tried the link I just thought it used an invert() filter :)
“CSS Sprites as we both know has no limitations or rules on how we have to put ALL images on one image. The only difference I can see technically from this technique and the real sprites is that one uses a background image and this uses and actual image.”
Semantically speaking, this is not what sprites are. Sprites are not a CSS technique. Sprites are a graphic technique that long predates CSS. It is about using parts of a larger image to compose smaller images from its parts. Please see “Sprite sheets” for classic raster games made for systems with very limited memory.
CSS sprites are basically a CSS implementation of that core *idea*. It has nothing to do with things being background images or otherwise (in fact, for a site I’m making now I’m using the sprite technique with regular old img tags and overflow: hidden). What sprites do is save on overall compression and, more importantly, HTTP requests.
So while you have a nice trick, it really has nothing to do with sprites.
Thanks for the replies guys, I am diggin the debate/conversations going on, its making me think!
@Chris I agree, the client does need to prep the image in a proper way. But again, he is capable of doing this rather than learning how to write css. This was the point of my tutorial. It’s much easier for someone to stack images and save file as, compared to dealing with css background positioning and dealing with class naming conventions.
*****
@Nowak
1. “It is about using parts of a larger image to compose smaller images from its parts. “

You are right, this is a simple example of that.
Look at the image being used below:
2. ” It has nothing to do with things being background images or otherwise (in fact, for a site I’m making now I’m using the sprite technique with regular old img tags and overflow: hidden). “
Well you just contradicted yourself. “I’m using the sprite technique” … So while you have a nice trick, it really has nothing to do with sprites.
The technique you said you were using, is similar to the technique being taught here. *Regular old img tags and overflow hidden ;-) Are they sprites or are they not?
*****
In the end, we can debate about what is and what is not a sprite all day till the cows come home. I am open to be corrected anytime so please understand I am not debating for pride’s sake.
My take is that you make your techniques and methods work efficiently to your specific project and situation. In my my scenario this worked smoothly and I felt it might benefit others in a similar situation. For those who found it useful, great! If not, maybe next time ;-)
@Chris
I see your point as the “swap” does not look dramatically different.
It is a sprite per se though, but – as you point out – one could wonder why SOH uses two pairs of images rather than a sprite grouping all images uses for the demo. Isn’t what sprites are made for?
Regarding the “big picture”, it was meant to be a pun (big picture > sprite). I did forgot the smiley though or it was lost in translation :-(
@Nick “Wow! I really can’t believe someone didn’t think of this before”
Actually, somebody did :)
Just so you guys have a visual of what my client actually uses to update his images:
Again, the goal here is keep it simple as possible so the client can update his images with the hover effect that he was looking for.
This is why adding all images on one image is not reasonable. This way the client is able to update his images using a simple image editor ;-)
@Chris: I thought I was the first to notice this. I was afraid.
This is quite doable using real sprites, but the article completely put the sprites aside. The example isn’t really showing sprite, so maybe it would be nice to change it to reflect this.
Anyway, the css can be shorter, because “margin-top:-10px” is shorter than “background-position:0 -10px;”.
But I still see a real problem here: if you have some hard caching policy (Cache: public, Expires: +1 year), you can’t change the sprite image easily without changing all the references to the sprite inside your HTML code. Using the CSS allows to manage this easily. My sprite has the version number in it: sprite-1.png, sprite-2.png and is highly cacheable (as of other ressources). If I change it, I only need to change 1 line in my CSS file to propagate the modification.
Nice post! Really, i woul try your solution in next site.
Simple and useful
Hi, Soh,
The tutorial is great. I am your regular visitor. Everyday I come to your website to look if you have something new.
These kinds of tutorials make me happy. Thanks again.
This does not degrade very nicely – it could be very confusing for situations where CSS is not supported or available on the client. Imagine a row of 6 social media icons using this method… If CSS were disabled, the user would see 6 identical images, each containing 6 icons. This would be meaningless to the user. CSS sprites degrade much better as they allow you to replace text; if the client does not support CSS, the user will still see text that means something to them.
A creative workaround that simplifies the needs of your client, that’s what I call user-centric design. Sometimes we creatives get our heads too stuck up our asses on what is or what is not an elegant solution… “Code is poetry” comes to mind :)
Food for further thoughts on the ongoing discussion, though.
I have been thinking about using the technique for quite a while but I wasn’t sure how to feel about it. I’m stoked to see you wrote an article on it.
I really like this method, especially since it allows the client to do his own updating and have the rollover effect. The CSS3 degrades really nicely too; I like when it’s used to enhance a page/site, not as a design crutch.
@Jayphen – Dude, read the article BEFORE you comment.
@Laneth Sffarlenn – Thank you so much!
“It’s much easier for someone to stack images and save file as, compared to dealing with css background positioning and dealing with class naming conventions.”
If you don’t want to use CSS Sprites, why to deal with negative margin for those images (containing both mouse statement) when you can just simple use different images for every banner mouse statement?
I don’t see any easiness in using negative margin instead of CSS sprites.
Totally agree with Chris Heilmann.
@Ken, if you used different images, then the client would have to upload 2 images and enter 2 images in the “add new link” section. This way, the client only uploads one image and its done. Again, the whole concept was to make as simple as possible for the client.
@Stephanie I did read the article. It doesn’t address my comment.
if you use one image instead of two, why not using CSS sprites?
@Hector Hurtado nailed my point ;-)
@Jayphen, typically its wise to use analytics to see how many users are on text-readers or browsers that don’t support CSS. You should be choosing your methods with this approach for any project. So perhaps you have a good amount of people w/ no support for CSS, in that case, this technique is obviously not the way to go for you. In my scenario, this was not the case. This is similar with users on older browser like IE5 for example. Support it or not support it? It all depends on your users and demographics. In the end, if the user can still access the information I think it is all fair game. You should always design and develop with your target audience in mind, and fall back solution that is still accessible for those that are not.
@Savageman Another example of a very specific situation. If your client is on a caching system, its up to you the designer to make the right choices. There are billions of tutorials out there, but they are out there as a tool and reference. Its just as much of a skill to be able decipher your situation and choose the most effective method for your project, client, and users. You make the call, I am only here to share things that I learned along the way ;-)
@Ken, have you read the article? It seems most people are jumping to a conclusion straight off of the title…
“The first approach in my mind was to do the typical CSS Sprites but this requires CSS work which my client did not know much of. I wanted to give him the access to update his affiliate banners using WordPress, and the simplest thing was to let him just upload his own images and put the URL in a custom field. No CSS tweaks involved, just what he needed.”
Soh,
great tutorial! This is just what I was looking for, unfortunately, I’m having an odd problem. When attempting to hover over any of the images within the div, all of the images change to there hover position as opposed to just the one I’m actually hovering over. Appreciate the help!
Very Nice! Used it with advertisement templates on the sidebar
THANK YOU… i was looking for a place with qualified CSS plus the frontend user in mind :D.. this little image hack was exactly what i was browsing for. MR. please make more of these super Tut’s.
@Josh, make sure your images are wrapped individually within each
atag.Soh, thanks! That was my issue, working perfectly now! :)
Nice tip bro! Thanks for sharing it with us!☺☺☺
I like website design more than article but here is lots of thing to learn.
Great job. cheers
Hi Soh,
Quick question for you, is there a way to get the images so move vertically on mouseover rather than just appear in mouseover state, like the 2 images in the center-right of the homepage on the oakley.com website?
Thanks much for such an AMAZING resource for us designers who are very familiar with code, but not back-end coders!
— Brian
Great, this gives me a nice little idea to work upon for my blog design. thanks a lot.
Hello, wonderful tutorial i tried it my self but i got an annoying background on the i added and i got this blue annoying border on firefox. how can i fix it?
Please e-mail me afrozenminute@yahoo.com
TY
Oh yeah i forgot here is the screenshot -> http://www.imgcafe.com/uploads/capturrir.png
HTML Markup
Soh,
Is there an easy way to add padding and border on the link. I’ve played with different variations but because of the overflow: hidden, the padding gets cut off on the bottom. I love how clean this code is for the effect. Would be nice to not have to add anything else.
.affiliates a {
width: 204px; height:182px;
overflow: hidden;
float: left;
border: 1px solid red;
}
.affiliates img {
border: none;
padding: 5px;
}
Soh,
In regards to my previous comment about padding and borders. I was able to somewhat accomplish this in two ways. Still hoping maybe you know of a better way that I’m overlooking.
Solutions:
- Instead of using padding, I used a border on the a:link of 5px.
- For the actual border, I then used outline: 1px solid black; or CSS3 box-shadow: 0 0 1px black;
Problems:
- The actual border using the “outline” property, doesn’t adapt to CSS3 border radius.
- Again, the actual border using the CSS3 “box-shadow” property, you don’t get the color value your looking for because of the shadow transparency. It also isn’t as crisp.
Thanks in advance for any help you may be able to offer!
gr8 one !! simple n quick !
Speak Your Mind...