You might be familiar with the plugin jQuery Dock which allows developers to create a menu like Apple Dock. Today, you will create a similar menu with bubble effect by using CSS only. Although it doesn’t have as smooth of an effect as jQuery Dock, it’s helpful for those that just want to make a cool menu by using pure CSS. This tutorial includes two methods: CSS sprites (basic) and the image swapping (advanced).
Like the article? Be sure to subscribe to our RSS feed and follow us on Twitter to stay up on recent content.
Big thank to Erik Zettersten as an editor.
Check out the demo or download.
Method 1: CSS Sprites
Using CSS sprites is the simplest way to make the bubble effect. You just need to change the background images- and that’s it.
But at first, your HTML should look like this:
<ul id="bubble"> <li> <a class="icon feed"href="http://feeds2.feedburner.com/prlamnguyen"title="Full RSS Feed">Full RSS Feed</a> </li> <li> <a class="icon email"href="http://feedburner.google.com/fb/a/mailverify?uri=prlamnguyen&loc=en_U"title="Feed via Emal">Feed via email</a> </li> <li> <a class="icon twitter"href="http://twitter.com/prlamnguyen"title="Full RSS Feed">Follow me on Twitter</a> </li> <li> <a class="icon facebook"href="http://facebook.com/duylamng"title="Full RSS Feed">I'm on Facebook</a> </li> <li> <a class="icon delicious"href="http://delicious.com/save"onclick="window.open('http://delicious.com/save?v=5&noui&jump=close&url=http://aext.net&title=AEXT.NET', 'delicious','toolbar=no,width=550,height=550'); return false;"title="Full RSS Feed">Save me</a> </li> <li> <a class="icon technorati"href="http://technorati.com/faves?sub=addfavbtn&add=http://aext.net"title="Full RSS Feed">Fave me</a> </li> </ul>
After you prepare the image for sprites, it should look like this:
This is the CSS code you need to make up the list of menus and the default background image of links:
#bubble {
list-style: none;
margin: 0px;
padding: 0px;
}
#bubble li {
display: inline-block;
margin: 0px;
padding: 0px;
}
#bubble li a.icon {
background: url(images/sprites.png) no-repeat;
border: none;
display: block;
width: 128px;
height: 128px;
text-indent: -9999px;
}
It’s very important while using CSS sprites to calculate the dimensions of the background images. You have to make sure to be pixel precise. Refer to the image above. You’ll need to use the CSS below to change the background image of link elements.
#bubble li a.feed {
background-position: -139px -12px;
}
#bubble li a.feed:hover {
background-position: -13px -12px;
}
#bubble li a.email {
background-position: -139px -149px;
}
#bubble li a.email:hover {
background-position: -13px -149px;
}
#bubble li a.twitter {
background-position: -139px -283px;
}
#bubble li a.twitter:hover {
background-position: -13px -283px;
}
#bubble li a.facebook {
background-position: -139px -422px;
}
#bubble li a.facebook:hover {
background-position: -13px -422px;
}
#bubble li a.delicious {
background-position: -139px -559px;
}
#bubble li a.delicious:hover {
background-position: -13px -559px;
}
#bubble li a.technorati {
background-position: -139px -698px;
}
#bubble li a.technorati:hover {
background-position: -13px -698px;
}
And that is Method 1: very easy and simple. Now, let’s go to Method 2, the image swapping.
[smartads]
Method 2: The Image Swapping
With this method, you will use more of HTML, and less CSS. Because we will use 2 images for each link, the complete code of HTML is should look something like this:
<ul id="bubble2"> <li> <a href="http://feeds2.feedburner.com/prlamnguyen"title="Full RSS Feed"> <img class="small"src="images/feed.png"alt="Full RSS" /> <img class="large"src="images/feed_large.png"alt="Full RSS" /> </a> </li> <li> <a href="http://feedburner.google.com/fb/a/mailverify?uri=prlamnguyen&loc=en_U"title="Feed via Emal"> <img class="small"src="images/email.png"alt="Feed via Emal" /> <img class="large"src="images/email_large.png"alt="Feed via Emal" /> </a> </li> <li> <a href="http://twitter.com/prlamnguyen"title="Follow me on Twitter"> <img class="small"src="images/twitter.png"alt="Follow me on Twitter" /> <img class="large"src="images/twitter_large.png"alt="Follow me on Twitter" /> </a> </li> <li> <a href="http://facebook.com/duylamng"title="I'm on Facebook"> <img class="small"src="images/facebook.png"alt="I'm on Facebook" /> <img class="large"src="images/facebook_large.png"alt="I'm on Facebook" /> </a> </li> <li> <a href="http://delicious.com/save"onclick="window.open('http://delicious.com/save?v=5&noui&jump=close&url=http://aext.net&title=AEXT.NET', 'delicious','toolbar=no,width=550,height=550'); return false;"title="Save me"> <img class="small"src="images/delicious.png"alt="Save me" /> <img class="large"src="images/delicious_large.png"alt="Save me" /> </a> </li> <li> <a href="http://technorati.com/faves?sub=addfavbtn&add=http://aext.net"title="Fave me on Technorati"> <img class="small"src="images/technorati.png"alt="Fave me on Technorati" /> <img class="large"src="images/technorati_large.png"alt="Fave me on Technorati" /> </a> </li> </ul>
In this method, we will make some changes. The hover effect will make the hover button stay on top of others. The difference between method 1 and this one is that you have to set the height and width for <li> elements. Why? Because we don’t want the list moving and changing sizes when the mouse is over it. So, the CSS code for the list is:
#bubble2 {
list-style: none;
margin: 20px 0px 0px;
padding: 0px;
}
#bubble2 li {
display: inline-block;
margin: 0px 5px;
padding: 0px;
width: 72px;
height: 72px;
}
72px is the size of small images. You can set it bigger, but don’t make it too big.
CSS for the links is:
#bubble2 li a img {
position: relative;
border: none;
}
#bubble2 li a img.large {
display: none;
}
#bubble2 li a:hover img.small {
display: none;
z-index: 0;
}
#bubble2 li a:hover img.large {
display: block;
margin-top: -28px;
margin-left: -28px;
z-index: 1000;
}
Remember to set position of the images to relative, because we will set z-index for the large images when mouse over is larger then other, and the z-index works only with position relative or absolute.

When the mouse is overtop, we will set margin of images to -28px because when we enlarge the images, we want the large one have the center same as the small one. It’s very important to see the zoom effect. The amount of pixel we need to margin is calculated as: margin-top= – (height of large – height of small)/2 and margin-left= – (width of large – width of small)/2.
Finally, add these code to your HTML file to display correct list in IE:
<!--[if IE 7]> <style type="text/css"> #bubble li, #bubble2 li { display: inline; } </style> <![endif]-->
And that’s it.
You can use z-index for method one, too. This tutorial just separates the two methods so you can choose. You can choose between two methods above: one you have to write more CSS code but less HTML, another one you have write more HTML code but less CSS code.


like the effect, thank you.
Nice job with this one. Looks smooth
Thanks for the tweet, Kawsar
You can also have these animated, in CSS3 supported browsers:
http://css-tricks.com/examples/QuickieCSS3Tricks/
Using animated gif of a growing button, you should be able to recreate the JQuery doc animation completely in CSS.. ?
@dirk digizaal webdevelopment: Yes, you can do it via jQuery. Take a look at my sidebar, the bookmark section. I’m using jQuery to make it smoother.
Using negative margins (eg: #bubble li { margin:0 -17px; } ) you could bring those icons closer together on the first example… Just a thought.
@Luke – Yes, sure! In this post, I have mentioned that you could do the same effect and margin as method 2 for method 1
However, if you use negative margin just simple like this, you will make the li elements moving.
I though it need some more complicated css code.
Great article and really interesting you’ve included both methods… usually developers stick to their strongest prefered language and use that to produce the desired effect.
I’ve always thought of progressive enhancement being about seperating your layers of CMS (your content),markup (how you can inject into the content), css (styling and brief interaction of your markup/content), javaScript (your full client-side interaction) and then the backend for additional dynamic data from your CMS/DB etc.
For that reason, if I were writing a conclusion I would suggest using HTML would be the incorrect method (when thinking about progressive enhancement).
I always disable my CSS/jS and hope to see almost a word document displayed for the reasons above. What do you think?
nice effect i like, many thanks for the tut..
Wow this looks great. What license is the CSS released under ? Thanks for sharing your work
Really cool css job, will try this out soon.
Thanks.
Great tutorial dude. Very nice effect. And, i’ll try make the jQuery smooth animation like you did in sidebar.
Thanks again
Although a bit flickery in IE8, really smart effect!
I guess you can pull up the top margin to about -100px for IE8 using conditional comments.
Thanks for the writeup, great info
I know I’ve looked something like this up a few times, I’ll bookmark this for the next design I have to edit.
oh,come to this site is just like in heaven!! i was just dream to have something like this in my homepage a few hours ago when suddenly i found this page while browsing..thanks to sir Lam Nguyen!! i love this tutorial and the codes itself.I iimplement the second codes coz it’s much easier for newbies like me
thanks again Lam!
Thanks for sharing,
I have a question. Is it possible to make the Images larger than 128px?
Nice one, really. Gonna implement that one on my profile page for linking to social media profiles.
This is a cool effect.
Thanks for this detailed description.
Really like this effect, gonna use it on a price table structure today.
Thanks for the details and source.
You could do the same thing with CSS3 and the scale property. If your running Safari or Chrome check out my blog’s footer for an example!
Nice tutorial!
Note that you can add this CSS rule :
#bubble li a.icon {
overflow:hidden;
}
And when clicking on the sprited version will remove the outline that include the text indent to the left and make the ouline really represent the icon.
@Kai Chan Vong – Why using HTML would be incorrect method?
@boiss – Oh, I forgot that we have to disable the outline border
Very nice tutorial ..
Thank for sharing good stuffs.
whoa! great! sooo powerful!
next time, teach us too about ABCs
Great Information! Thanks for sharing!
@Lam – You’re totally right, that’ll teach me for skim-reading..
thank you for this article I benefited from it .
زيروجيت – تطوير – برمجة – كمبيوتر – php – Ø¬Ø§ÙØ§ سكربت
Great design thanks. I have shrank the images but in ie8 they become a list rather than across the page. Any suggestions?
Nice lesson
Nice, thanks for the idea… it’s kind of like a static dock effect. *tweeted*
I suppose that even blogs with the most absolutely basic “tutorials” can even attract attention. This is such a basic concept that anyone with even a basic knowledge of CSS should have already been able to do it.
I don’t think it’s basic or obvious at all. I see I’ve actually done this before, the CSS ‘pixy’ way, but didn’t realize it because the purpose and appearance of this is so different. I think it’s a great tutorial.
@Lam Nguyen
I’d say using HTML would be incorrect because the outcome without CSS/jS would be for 2 images of varying size to be side by side for each link.
My thinking is that if CSS/jS doesn’t exist, then you should have almost a word document like layout which does make sense and has semantic data on the page.
Let me know what you think/disagree and why!
Very Nice article
Thnk u mate .. loved it ..
..
.-= Sid´s last blog ..5 Most Effective Tricks to become a Successful Blogger =-.
IE 8 issue: The image swap method doesn’t work in IE 8, even the demo page has the same issue I was experiencing. The bubbles are displaced low on hover. Unable to work out what is causing it, anyone?
nice effect i like, many thanks for the tut..
what a nice tutorial. thanks
.-= Exclusive Tutorials´s last blog ..3 simple steps for automatic database backup =-.
Nice and cleanly laid out tutorial, this will come in useful for browsers that have script disabled.
.-= fb´s last blog ..WordPress 3.0-alpha and qTranslate =-.
Thanks very much for this very good article. I tried this on my blog using my own icons
.-= Akbar´s last blog ..F1 | Massa: I am Very Pleased =-.
great tutorial for me as I’m a new lover of CSS. I tried Mathod2 on my blog. at first in IE it all messed up then i had to change this ” #bubble2 li a:hover img.large {
display: block;” to ” #bubble2 li a:hover img.large {
display: inline-block;”..
help me friends to learn more. I’m only relying on online resources.
.-= Akbar´s last blog ..F1 | Massa: I am Very Pleased =-.
This is an incredible post. Its amazing to see what CSS3 can do , at the same time its sad a lot of customers still want IE support which sucks at CSS3 big time. I am taking the liberty of adding this article to my CSS aggregator site. Hope you dont mind.
Nice stuff round here, this way we’ll definately get a hang of some nice CSS techniques, keep it up!
cam on nhieu .
great effects and tutorial
Great job. Where can i find the psd pictures of this example ? I need to create others social icons like the example. Thanks.
nice effect i like, many thanks for the tut..
totally awesome tutorial, brilliant one admin. I really love your work. thanks for sharing and can’t wait to see more of your codes. im glad i droped by. thanks.
This is interesting, I’ll try it on my next project. Very cool!!
Thanks for the writeup Lam…
Nice post…