I’ve had this example in mind for a while now and seeing something similar in the wild, made me want to write this article down.
So, in this article you’ll learn how to create an interactive menu using CSS3 goodness and jQuery’s power.

The idea
The idea behind this example was to have some nicely arranged blocks and once you click on one of them, the block will start showing its hidden content starting at its current position.
Besides being a menu, this example can also serve as a perfect single page website. For example, just think that a block can be named “Contact” and could contain a nice contact form.

The HTML
Nothing too complicated here, each block has a title that is hidden once its adjacent content will be triggered. Regarding tabindex will discuss a little later.
<ul class="menu">
<li tabindex="1">
<span class="title">One</span>
<div class="content">Lorem ipsum dolor sit amet...</div>
</li>
...
<li tabindex="1">
<span class="title">Nine</span>
<div class="content">Lorem ipsum dolor sit amet...</div>
</li>
</ul>
The CSS
In the following rows I’ll try to explain a bit the styles that were used to create this example.
Wrapper
First of all we’re going to add some basic styles for our list wrapper including clearing floats. Also, you may have noticed the counter-reset: li; declaration, you’ve seen it before and we’ll use it further again to create a nice counter effect.

.menu{
width: 620px;
margin: 100px auto; padding: 15px;
list-style: none;
counter-reset: li;
background: #eee;
box-shadow: 0 1px 2px rgba(0,0,0,.1) inset;
border-radius: 10px;
}
.menu:before,
.menu:after {
content: "";
display: table;
}
.menu:after {
clear: both;
}
.menu {
zoom:1;
}
List element
Below you can find the CSS rules used in order to add some basic styles for list elements.
Things to note:
- On
:focuswe’ll use the same styling as on:hover. This is necessary when using keyboard’s tab key. - The CSS
.coverclass is dynamically added (with jQuery) to anlielement when it’s triggered. - If the trigger is made through ENTER key, using
outline: 0;declaration will help removing focus styling. - Numbering system, similar to CSS3 ordered lists.
.menu li {
position: relative;
float: left;
cursor: pointer;
height: 120px; width: 200px;
margin: 10px 0 0 10px;
color: #fff;
}
.menu li:hover, .menu li:focus{
background-image: linear-gradient(top, rgba(255,255,255,.2), rgba(255,255,255,0));
}
.menu .cover{
z-index: 2;
}
.menu .cover:focus{
outline: 0;
}
/* -------------------------------- */
.menu li::after{
content: counter(li);
counter-increment: li;
font: italic bold 10px serif, georgia;
position: absolute;
color: rgba(255,255,255,.1);
opacity: 0;
transition: all .2s ease-out;
}
.menu li:hover::after, .menu li:focus::after{
font-size: 100px;
opacity: 1;
}
.menu .cover::after{
z-index: -1;
}
Clean li’s margins and colorize them
Above we’re using margin: 10px 0 0 10px; to add spacing between elements, now we have to clean some of them. Also we’ll colorize the li elements along with its content window and close button.
In this case, to colorize .content and .close for each li, it would have been great to just use background: inherit; declaration. But, due browser inconsistency we’re going to use the “hard” way, as you can see below:

.menu li:nth-child(1),
.menu li:nth-child(2),
.menu li:nth-child(3){
margin-top: 0;
}
.menu li:nth-child(1),
.menu li:nth-child(4),
.menu li:nth-child(7){
margin-left: 0;
}
/* -------------------------------- */
.menu li:nth-child(1),
.menu li:nth-child(1) .content,
.menu li:nth-child(1) .close{
background-color: #2c618f;
}
.menu li:nth-child(2),
.menu li:nth-child(2) .content,
.menu li:nth-child(2) .close{
background-color: #91ab31;
}
.menu li:nth-child(3),
.menu li:nth-child(3) .content,
.menu li:nth-child(3) .close{
background-color: #714a28;
}
.menu li:nth-child(4),
.menu li:nth-child(4) .content,
.menu li:nth-child(4) .close{
background-color: #e58600;
}
.menu li:nth-child(5),
.menu li:nth-child(5) .content,
.menu li:nth-child(5) .close{
background-color: #c33a00;
}
.menu li:nth-child(6),
.menu li:nth-child(6) .content,
.menu li:nth-child(6) .close{
background-color: #7f5dac;
}
.menu li:nth-child(7),
.menu li:nth-child(7) .content,
.menu li:nth-child(7) .close{
background-color: #5672b7;
}
.menu li:nth-child(8),
.menu li:nth-child(8) .content,
.menu li:nth-child(8) .close{
background-color: #69003f;
}
.menu li:nth-child(9),
.menu li:nth-child(9) .content,
.menu li:nth-child(9) .close{
background-color: #393043;
}
Title, Content and Close
Regarding the styles for .content window:
- When the
.expandedclass is added to it, its height and width are transitioned to cover the entire list. - Please notice the comments to see how the elements in the grid “respond” once they’ll be triggered.

In this screenshot, you can see the fifth block hovered.
.menu .content{
opacity: 0; display: none\9;
overflow: hidden;
font: 12px Arial, Helvetica;
position: absolute;
height: 120px; width: 200px;
transition: all .3s ease-out;
}
.menu .expanded{
opacity: .95; display: block\9;
overflow: visible;
padding: 40px;
height: 300px; width: 540px; /* Cover the entire area */
}
.menu li:nth-child(3n) .content{ /* 3,6,9 */
right: 0;
}
.menu li:nth-child(3n-1) .expanded{ /* 2,5,8 */
left: 50%;
margin-left: -310px;
}
.menu li:nth-child(7) .content, /* 7,8,9 */
.menu li:nth-child(8) .content,
.menu li:nth-child(9) .content{
bottom: 0;
}
.menu li:nth-child(4) .expanded, /* 4,5,6 */
.menu li:nth-child(5) .expanded,
.menu li:nth-child(6) .expanded{
margin-top: -190px;
top: 50%;
}
/* -------------------------------- */
.menu .title{
position: absolute;
height: 100%; width: 100%;
text-align: center;
font: italic bold 1em/120px 'trebuchet MS', Arial, helvetica;
opacity: .2;
}
.menu li:hover .title{
opacity: .7;
}
/* -------------------------------- */
.menu .close {
/*background: inherit;*/
display: none;
border: 5px solid #fff;
color: #fff;
cursor: pointer;
height: 40px; width: 40px;
font: bold 20px/40px arial, helvetica;
position: absolute;
text-align: center;
top: -20px; right: -20px;
border-radius: 40px;
}
.menu .cover .close{
display: block;
}
The jQuery
Below you have the jQuery code, I think it’s quite easy to follow and understand:
(function(){
// Append a close trigger for each block
$('.menu .content').append('x');
// Show window
function showContent(elem){
hideContent();
elem.find('.content').addClass('expanded');
elem.addClass('cover');
}
// Reset all
function hideContent(){
$('.menu .content').removeClass('expanded');
$('.menu li').removeClass('cover');
}
// When a li is clicked, show its content window and position it above all
$('.menu li').click(function() {
showContent($(this));
});
// When tabbing, show its content window using ENTER key
$('.menu li').keypress(function(e) {
if (e.keyCode == 13) {
showContent($(this));
}
});
// When right upper close element is clicked - reset all
$('.menu .close').click(function(e) {
e.stopPropagation();
hideContent();
});
// Also, when ESC key is pressed - reset all
$(document).keyup(function(e) {
if (e.keyCode == 27) {
hideContent();
}
});
})();

Visible content window for the fifth element.
Graceful degradation
Regarding opacity, due its lack of support for older browsers, you’ll need to use the display toggleing for IE Trident:
opacity: 0; display: none\9; /* Initially hidden */ opacity: .95; display: block\9; /* Expanded */
Other existing CSS3 stuff like transitions and gradients and just play nice where the support allows it.
Selectors
As you already noticed, we’ve used some CSS3 selectors that older browsers like IE8 and below do not support.
So, we need a solution that fixes the example for those browsers. In my opinion, the best solution in this case is to use the Selectivizr tool, as we’ve already included jQuery in our project. That’s because Selectivzr requires one of those JavaScript libraries: jQuery, MooTools, Prototype etc. in order to work.
<!--[if (gte IE 6)&(lte IE 8)]> <script src="selectivizr.js"></script> <![endif]-->
Thoughts on accessibility
The cool part is that along with HTML5, the tabindex attribute can be used on any HTML element. We’ll be using that in our example to enable tabbing navigation: <li tabindex="1">.
I really wanted this example to be accessible via keyboard and I made it. When tabbing, you have the possibility to trigger a window by pressing the ENTER key and then close it by pressing the ESC key:
// ENTER
$('.menu li').keypress(function(e) {
if (e.keyCode == 13) {
showContent($(this));
}
});
// ESC
$(document).keyup(function(e) {
if (e.keyCode == 27) {
hideContent();
}
});
That’s it!
I hope you liked this article and I’m looking forward to read your thoughts about it. Thanks for reading!
Kinda look based on this article: http://tympanus.net/codrops/2012/04/09/direction-aware-hover-effect-with-css3-and-jquery/ right?
Tavi, when I said “seeing something similar in the wild” I meant a real working example, not a tutorial.
Regarding Codrops’s article, I’ve seen that before but I don’t think they are similar at all and neither the code and functionality. ;)
I see there are 2 human with same name “rosu” , very cool article
It’s really very nice.. great work. Thanks for posting :).
@Tavi Rosu: its not even close to the one you showing both are so different.
I’m glad you like it and thanks for your support :)
Сatalin, your interactive menu is clean and a lot of work.
This menu is one of the finest solutions to save space on a web page without harm to the design and usability.
It is a synthesis of all the menus and pages of announcements – the user can know in advance what to expect when clicking on the link. This is a very important right now, especially when the user appreciates his time.
Wonderful work, thank you!
Thanks for your comment Catherine!
Indeed, I spent some time working on this project but I think it’s worthwhile. Besides design and usability, I’d say that accessibility is also a big plus here as it’s quite easy to navigate it using a keyboard.
Frankly, Catalin, I do not even checked on the ability to move with the keyboard :(
Wow, that is such an opportunity – it is very good for users with disabilities.
Thanks very much, I really like this. I just have a problem with Mac using Chrome and Safari. If I add several lines of content, after closing a block, it still keeps the block highlighted at its expanded size. And it’s still clickable at that expanded size. This doesn’t happen with Firefox. Not sure how to fix this. To see what I mean add about 8 lines or so of content rather than the one or two in the demo.
Frank, thanks for your good feedback!
That small bug should be fixed now. I updated the article, demo and .zip archive ;)
Wow, that was fast. Thanks so much. Just downloaded the zip again and now it works great with the added content. Your site is my favorite for really interesting practical applications of css3, html5 etc.
I downloaded your great interactive menu a few days ago and am having the same problem as Frank. Chrome leaves weird orange lines and Safari leaves blue outlines. You can see it in dualproject’s site http://www.dualproject.it/design if you open in either of these browers and even in your demo. Would love to get this remedied :)
Kim, the
li‘s are focusable and that orange/blue outline is inherited from browser’s defaults.Here’s how to overcome it:
.menu li:focus { outline: 0; }Thank you so much for the quick reply Catalin, works like a charm! I was just getting ready to google the problem when I noticed your email. I only wish I had a tenth of your knowledge. :-)
You have street cred. I always admire you to lead us a new discovery with common knowledges.
Thank you for your Socrates teaching method:
http://www.cut-the-knot.org/proofs/half_sq.shtml
hey, really nicely done!
thanks for sharing.
One thing that I would do to improve your jQuery is to use .on() rather then .click().
Thanks Peter, your suggestion is good and I’ll keep that in mind.
Really great job !
thanks for sharing it with us
I feel like this article could be done more efficiently and simply, but it’s great nonetheless. :)
:) I try to do my best and I’m always open to suggestions in order to improve my articles.
I just saw your awesome menu and thought of making a copy of it just using CSS3 and no jquery, I made it here is the link for it. Suggest me if I can improve it cause its little bit buggy
http://webstutorial.com/css3-portfolio-menu/css3
So, you made a copy of it, and still no link back. Pretty sad. :|
Also, IMHO, besides being buggy it’s quite far from the initial idea too.
Sorry for no backlink, I ll just add it now. Yaa its buggy cause its fully in CSS3 and I changed the concept to portfolio
hey if i may ask can this menu be turned into a photo gallery if so please let me know how i can do it
With some effort, of course you can turn this into a a grid photo gallery. Sounds like good idea for a future article :)
i thought that was actually possible by simply playing around with the codes and u get the thing nways i hope u can do it within the next fews days coz i would greatly want to have it
man, this is cool. i like the expand function.
Hi , how do you make it work on IE8 apparently i cannot get it to work , it might be something with the selectivzr.js file
Martin, if you want to test Selectivzr on your computer, try using a web server as XAMPP.
Still dosent work in IE8….
I have the same issue aswell
Hi Catalin,
I am new to web development and I have been learning lots from your tutorials.
I downloaded the files and was trying my on stuff. Instead of 9 blocks I just have 3 blocks, now that makes my actual page small. When I click on one of the box the actual content is cropped by the footer. Is it possible to auto resize the page? so If I click on one of the box the page resizes to fit the content and when I close it will resize the page to the normal size.
cheers
Hi,
In case you have just three blocks, I’d recommend you to increase their height and also adjust the
.expanded‘s height.This way you’ll keep the aspect ratio and your content will fit. I think this is the best solution.
Hope that helps!
Catalin
I love this!!!! Is there a non css3/html5 option? I have a client that is married to ie, and css3 and html5 won’t work with his site … =(
Thanks!!!!!!
Hi,
The cool thing is that this demo works also on IE6! ;)
I disabled javascript and none of the content overlays work. Can you make this gracefully degrade if a person doesn’t have access to javascript/jquery?
Nice article ..!!!
Hello! This is great. I am very new however to the world of web design and development and although I understand most of the code, I am not certain about where the numbers are being generated when you mouse over each box. I.E. “1″ appears in the background of the box when the mouse is over the first box, “2″ on the second, and so on. Does that information live inside of the js itself? If so, where specifically? Thanks in advance for any guidance.
Crystal, you may want to check one of my previous articles to see how those numbers are rendered.
Hope that helps!
This is an awesome CSS3 menu! I am thinking I can modify this and use it for a futue website I am working on. This is a great space saver too where you can show a small snippet of info and then expand on it without coming out of the confines of the menu. And it sort of reminds me of the new WIndows 8 Metro style!
Awesome, thanks very much for sharing this.
Peter
Hello,
I was implementing this interactive menu on my webpage, when I noticed that the title (inside the squares) is not compatible with special characters (like: ã, í, ì). It generates some weird characters like the “c” of copyright. Any ideas on how to fix this?
It’s really very nice.. great work. Thanks for posting :).
This is one of my preferit javascript menù. My only dubit is that i had a lot of problem with browser compatibility.. Ok the real problem is that in Italy 40% of people use IE .. is possible to make that script work wit IE??
I also want to link this blog with the credits for the menù in my future website ( for now you can see it at : http://www.dualproject.it/design (no need to back link ^^)
Great Work
If in navi menu design 1, 2, 3 … changed on a image or icons – its be a real cool and very needs in my project ))))
What a splendid idea!
This kind of productive tutos is exactly what I was seking.
The plugin seems solid enough to test it on a production site. I’ll give it a try.
Inside a carousel for an overview of products, for example, when a slide is not enough…
you have inspired me today.
Thank you very much for the inspiration, and the plugin (of course!).
Stay creative, and all will be fine! Have a good day.
One question: I want to use this as part of my new website but not sure how or if this can be made responsive. Is it possible to show how to make this responsive? Any help is much appreciated! Thanks and great work once again!
I like it, but have spent HOURS trying to get the “title” text to wrap in the div so I can display more than one line of text. Is pretty useless if the front panel can only contain a few words.
Any ideas how to remove the “single text line restriction”? I have tried 100 things and nothing works.
Jeff, you need to remove the
120pxline-height for.menu .title…That should do it for you!
didn’t work. not sure why it would be so difficult …..
Hi why is the “Visible content window” is not working on my codes? what is the main header for jquery? pls help me thanks. where do i need to place the header for script? jquery?
hello
first of all thank you for this great css and html file
but there is a little problem,as you can see in demo after the box between the box and text of “Back to article / Drop me a ….” is a large space
how can reduce this space ?!
thank you
loving this, however i tried to include a link to another page in the content and it messed up the alignment, any idea why that would happen
what would be needed to changes this to 4 columns and 3 rows rather than the 3×3
thx your site is so cool
I think this is great too but am having a similar problem. I have eleven boxes in rows of three with 10 and 11 on the bottom row. The boxes display fine but when I hover over 1,2 or 3, it calls boxes 7,8 and 9 and when I click it displays the latter boxes contents. Hovering over the last 3 rows works fine, just the top one doesn’t. I have played around with this quite a bit but can’t get it working. Any help would be greatly appreciated. Thanks.
Como hago para cambiar, los números que me aparecen en el hover por el por letras. gracias espero pronta respuesta
Cesar, in the future I’d appreciate if you could try commenting using the english language. Thanks.
Now, while this is an automatic numbering system, you don’t have options to change the numbering system or type.
But, you can remove the numbers completely using:
.menu li::after{ content: ' '; }Me again Catalin.
Still can’t get one part working quite like I want it. I have the li set to opacity:1 and
the li:hover set to opacity:0.8. Works fine until the li is clicked and expanded. The expanded content also has an opacity of 0.8 even though .menu .expanded is set to opacity:1. If I move the cursor out of the area, the content opacity changes to 1 but when I move it back in it’s back to 0.8. I tried this the opposite way too and had the li at 0.8 and the hover at 1 which expanded to opacity:1. Then the area outside the menu had an opacity of 0.8 when focused. Is this a trickle effect.? I don’t understand jquery and wondered if something had to be changed in that part.
Hi – your menu is superb, I love the style
I have been playing around with it and have included a couple of hyperlinks on the ‘content’ div so they appear when the menu is expanded
My problem is that if I click the left hand side of the ‘title’ element to expand it jumps straight to my link
Is there anyway to disable hyperlinks when the content tab isn’t expanded?
thanks again
Aaron, not sure if I understand your issue. Maybe you can use jsFiddle to make a demo?
Solved it. I had assigned the same height & width to “.content” as I had to “.title” meaning the links were still clickable even though they weren’t visible. Just assigned a 0px value to the width attribute of .content
Glad to hear you managed to solve your issue ;)
so it turns out, thanks for the info
This is really fantastic! So many applications.
Two questions:
- Is it possible to change the li:after numbering to custom text for each block?
- How might this be modified so you can close the expanded window by just clicking again anywhere in the space instead of having to go back to the X in the corner?
Thank you, having a lot of fun with this so far!
1 – Yes, just change the value for the
contentproperty for each.2 – At this time, the window can be close by pressing the ESC key as well, but you can also use jQuery’s
event.stopPropagation()to hide it when clicking outside.3. Good luck! :)