Design Lunatic

CSS3 Lavalamp Menu

Today, I’ll be teaching you how to create a CSS3-only lavalamp menu. This menu will behave much like This jquery powered one, except for the keyboard control. Lavalamp menus are a unique way to add some creativity to your site, and if said menu is made with only CSS3 – that’s pretty cool.


The HTML here is very, very simple. It’s just a “ul” with some “li”s and links inside, as well as a “slider” div.

<ul id="nav">
<li><a href="#">Home</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">Help</a></li>
<li><a href="#">About</a></li>
<div id="slider"></div>

This is all you need.


The CSS for this is very reusable. It’s very easy to just copy-paste this into your CSS file and have it working almost instantly, since all you need is just an unordered list, which is the format most nav menus follow.

First off, we’ll just give the “body” a simple grey background.

body {
background: #fbfbfb;

Now, we can style the “nav”.

#nav {
background: white;
border: 1px solid #CACACA;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 0px 0px 3px 1px #ebebeb;
-moz-box-shadow: 0px 0px 3px 1px #ebebeb;
box-shadow: 0px 0px 3px 1px #ebebeb;	
height: 40px;
width: 400px;
margin: 0 auto;
margin-top: 50px;
position: relative;

Most of the stuff in there is purely for visual purposes, but one thing is necessary – the “position: relative”. Since our “slider” div will be “position: absolute”, we need it to be positioned “relative” to the nav.

Now, we just add some styles to the list items and the links inside.

#nav li {
float: left;
width: 100px;
height: 40px;
text-align: center;	

#nav li a {
color: #717171;
font-family: Arial;
font-size: 16px;
line-height: 40px;
display: block;
width: 100px;
height: 40px;

This is just for appearances, you can put whatever you want for these two elements.

The last thing we need to style is the “slider” div.

#slider {
left: 0px;
position: absolute;
top: 35px;
height: 5px;
background: #717171;
width: 100px;
-moz-border-radius-topleft: 0px;
-moz-border-radius-topright: 0px;
-moz-border-radius-bottomright: 10px;
-moz-border-radius-bottomleft: 10px;
-webkit-border-radius: 0px 0px 10px 10px;
border-radius: 0px 0px 10px 10px;
-webkit-transition: all 300ms ease;
-moz-transition: all 300ms ease;
-o-transition: all 300ms ease;
transition: all 300ms ease;

Once again, most of this is just for appearances, but there are a few necessary things in here. First of all, “position: absolute”. This allows us to put the div anywhere we want inside the “nav” without affecting any of the other elements. We also give it some CSS3 transition styling so that it smoothly animates to wherever we want it to be. One last thing about this div – it will animate back to whatever the “left” value originally is. Here, the “left” value is set to “0px”, so whenever the user hovers off of the menu, the “slider” div will move underneath the very first menu item. If you set the “left” value to be for example “100px”, the “slider” div will animate back to the second menu item when the user hovers off of the menu. This can be used to signal which is the currently active page.

Now, we can add the functionality to all this.

#nav li:nth-child(1):hover ~ #slider {
left: 0px;

#nav li:nth-child(2):hover ~ #slider {
left: 100px;

#nav li:nth-child(3):hover ~ #slider {
left: 200px;

#nav li:nth-child(4):hover ~ #slider {
left: 300px;

Boom. That’s it. Here’s how it works. When you hover over an “nth-child” of the “nav” menu, we use the “~” CSS selector to select the adjacent “slider” div and give it a new “left” value. The purpose of the “~” is to select any element that is after the first element. In our case, the “slider” is after each child of the “nav”, so we use the “~” to select it.

I hope you learned something useful from this tutorial. If you have any questions or comments, feel free to post them below.

  • Tgrace

    Wondering how then to trigger the slider to remain in the correct position for the current page — Does one have to create a separate style sheet then for each page, changing the left position of the slider accordingly?

    • Alexandre Smirnov

      Well, that’s one way to do it.  The simplest way would probably be to just use inline styles on the div depending on what page is active.  If you have a dynamically generated website, then there isn’t really a solution, since unfortunately “:target” doesn’t work with top level pages.

      • Tgrace

        I am trying this out in a wordpress site – but am hardcoding the menu. I don’t know about the :target pseudo class… Could you give me an example on how this is done?

        • Alexandre Smirnov

          Well, the “:target” selector is used to “target” an element that is in the url.  For example, if you have a div named “test”, and the url has “#test” appended to it, this code will fire:
          background: red;

          So if you have a link pointing to “#test”, or you append “#test” to the url via javascript, the “:target” event for that “test” element will fire.

          The thing is, “:target” doesn’t work with actual pages.  It only works with items appended to the current page.

          Since you’re using wordpress, you could use this tutorial:

          And adapt the code to work with the lavalamp menu.

          Good luck!

          • Tgrace

            Thanks. I’ll try that out!