From our sponsor: Ready to show your plugin skills? Enter the Penpot Plugins Contest (Nov 15-Dec 15) to win cash prizes!
In today’s tutorial we will create a full page cufonized menu that has two nice features: when hovering over the menu items we will move a hover-state item that adapts to the width of the current item, and we will slide out a description bar from the left side of the page, reaching towards the current menu item.
We will use jQuery for the effect and some CSS3 properties for the style. We are not going to use any images.
So, let’s start!
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
The Markup
The HTML structure will consist of an unordered list that represents our menu and a div for the description elements:
<div id="slidingMenuDesc" class="slidingMenuDesc"> <div><span>Description for "About"</span></div> ... </div> <ul id="slidingMenu" class="slidingMenu"> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Portfolio</a></li> <li><a href="#">Work</a></li> <li><a href="#">Contact</a></li> <li><a href="#">Get a quote</a></li> </ul>
We leave out the description for “Home” since there is nothing to describe. The sliding divs should just appear when we hover over the other items.
The CSS
First, we will style the menu and its navigation items and then we will style the description elements.
Let’s reset some styles:
body, ul, li, h1, h2, span{ margin:0; padding:0; } ul{ list-style:none; }
The background is going to be dark gray:
body{ background:#292929; }
The list for the menu items is going to be positioned absolutely at the right side of the screen:
.slidingMenu { position: absolute; height:410px; width: 410px; top:40px; overflow:hidden; right:1px; font-family: Arial, Helvetica, sans-serif; }
The menu items are hoing to float right:
.slidingMenu li { display:block; float:right; clear:both; position:relative; overflow:hidden; }
The “mover” element will be positioned absolutely and we will give it a top and a width dynamically:
.slidingMenu li.move { width: 9px; height: 68px; right:0px; padding-right:10px; margin-top:2px; z-index: 8; position: absolute; background: #2183c4; background: -webkit-gradient( linear, left top, left bottom, from(#0771b8), to(#2183c4) ); background: -moz-linear-gradient( top, #0771b8, #2183c4 ); -moz-border-radius: 8px 0px 0px 8px; -webkit-border-top-left-radius: 8px; -webkit-border-bottom-left-radius: 8px; border-top-left-radius: 8px; border-bottom-left-radius: 8px; -moz-box-shadow:1px 1px 5px #000; -webkit-box-shadow:1px 1px 5px #000; box-shadow:1px 1px 5px #000; }
We will give this moving hover element a very subtle background gradient and some box shadow.
The style for the link element will be as follows:
.slidingMenu li a { font-size:66px; text-transform:uppercase; text-decoration: none; color: #ddd; outline: none; text-indent:5px; z-index: 10; display: block; float: right; height: 66px; line-height: 66px; position: relative; overflow: hidden; padding-right:10px; }
The descriptions will be in a relatively positioned container. We set the margin-top to the same value like the top of the menu list:
/* Descriptions */ .slidingMenuDesc{ margin-top:40px; position:relative; }
The div with the description span inside is going to have the same background-gradient like the mover and the same box shadow. The rounded borders are going to be on the opposite corners:
.slidingMenuDesc div{ background: #2183c4; background: -webkit-gradient( linear, left top, left bottom, from(#0771b8), to(#2183c4) ); background: -moz-linear-gradient( top, #0771b8, #2183c4 ); height: 68px; padding-right:5px; left:-5px; width:0px; margin-top:2px; overflow:hidden; position:absolute; -moz-box-shadow:1px 1px 5px #000; -webkit-box-shadow:1px 1px 5px #000; box-shadow:1px 1px 5px #000; -moz-border-radius: 0px 8px 8px 0px; -webkit-border-top-right-radius: 8px; -webkit-border-bottom-right-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; }
We need to set these element absolute, since we will adjust the top to the according current list element that we are hovering.
The description span is going to be positioned absolutely as well. This is not required but it gives you more options if you would like to apply other animation effects:
.slidingMenuDesc div span { font-size:36px; color: #f0f0f0; text-indent:5px; z-index: 10; display: block; height: 66px; line-height: 66px; position:absolute; right:10px; margin-left:5px; top:-3px; }
And now, let’s take a look at the JavaScript!
The JavaScript
First, we will add the following scripts to our HTML head:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script src="cufon-yui.js" type="text/javascript"></script> <script src="BabelSans_500.font.js" type="text/javascript"></script> <script src="jquery.easing.1.3.js" type="text/javascript"></script>
And we will add the following script:
$(function() { Cufon.replace('a, span').CSS.ready(function() { var $menu = $("#slidingMenu"); /** * the first item in the menu, * which is selected by default */ var $selected = $menu.find('li:first'); /** * this is the absolute element, * that is going to move across the menu items * It has the width of the selected item * and the top is the distance from the item to the top */ var $moving = $('<li />',{ className : 'move', top : $selected[0].offsetTop + 'px', width : $selected[0].offsetWidth + 'px' }); /** * each sliding div (descriptions) will have the same top * as the corresponding item in the menu */ $('#slidingMenuDesc > div').each(function(i){ var $this = $(this); $this.css('top',$menu.find('li:nth-child('+parseInt(i+2)+')')[0].offsetTop + 'px'); }); /** * append the absolute div to the menu; * when we mouse out from the menu * the absolute div moves to the top (like initially); * when hovering the items of the menu, we move it to its position */ $menu.bind('mouseleave',function(){ moveTo($selected,400); }) .append($moving) .find('li') .not('.move') .bind('mouseenter',function(){ var $this = $(this); var offsetLeft = $this.offset().left - 20; //slide in the description $('#slidingMenuDesc > div:nth-child('+ parseInt($this.index()) +')').stop(true).animate({'width':offsetLeft+'px'},400, 'easeOutExpo'); //move the absolute div to this item moveTo($this,400); }) .bind('mouseleave',function(){ var $this = $(this); var offsetLeft = $this.offset().left - 20; //slide out the description $('#slidingMenuDesc > div:nth-child('+ parseInt($this.index()) +')').stop(true).animate({'width':'0px'},400, 'easeOutExpo'); });; /** * moves the absolute div, * with a certain speed, * to the position of $elem */ function moveTo($elem,speed){ $moving.stop(true).animate({ top : $elem[0].offsetTop + 'px', width : $elem[0].offsetWidth + 'px' }, speed, 'easeOutExpo'); } }) ; });
After we cufonize the font (all “a” elements and all “span” elements), the main function gets executed. We select the first item by default which is our “Home”. When we hover over a menu item we will move the li.move to the right position and slide out the according description item.
And that’s it! We hope you enjoyed it and find it useful!
This is a great menu!
Is there a way to have a corresponding background image for each menu item that fades in and out as you hover over. I am new to jquery. Thank you so much.
How to extend the css for different colors for each list item?
I try
http://www.ee.bilkent.edu.tr/~sefunc/
Can anyone assist me in figuring out how to make the description slider less opaque? The issue is that when the bar is opened it conflicts with underlying text, making it more difficult to read. Also, I have never touched html/css (any webpage design) until this past weekend, so I am more than green and trying to absorb as much as possible. Thanks.
Menu activate code… I don’t get this part:
—
var $moving = $(”,{
className : ‘move’,
top : $selected[0].offsetTop + ‘px’, /* <– this doesn't work */
width : $selected[0].offsetWidth + 'px'
});
$moving.css('top',$selected[0].offsetTop + 'px'); /* <– this fixes the problem */
—
Original code that I have is:
—
var $moving = $('’,{
className : ‘move’,
top : $selected[0].offsetTop + ‘px’,
width : $selected[0].offsetWidth + ‘px’
});
—
How this part should look like after modification?
Oops,
First line should look like this in original code line:
var $moving = $(”,{
This has been a great thread and I would like to reiterate all of thanks for this wonderful script ML.
Earlier I asked about making the sliding menu bars less transparent so that text could show through (I had 0 experience with anything prior to this past weekend) and I wanted to share my solution with everyone. I found that by using Adam’s pure CSS3 script I could then set ‘opacity: 1’ without having to worry about the javascript superseding the css; also, this pure CSS3 implementation seems to make the site function with IE9, which is nice.
Two other questions arose, if anyone can assist.
1) Is there anyway to make the CSS3 solution work with IE7 or at least display a nice information window to upgrade?
2) Any idea on how to put spaces into the name of the menu items without messing up view?
Hi Nathan,
any news about compatibility with Jquery from 1.6 or more?
Thanks.
does anyone know if this flyout menu has been causing issues with your navigation menus?
When mousing though my css navigation menu and rolling over top this flyout menu my css nav menu disappears and the flyout begins interaction.
the highest z-index on the flyout is 100
I just tested with a 1200 z-index, and a 100000 z-index (just to make certain) on my css nav menu.
Thanks.
can someone upload newest and working version ?
OR
blue block must stay behind the menu item which is active… i couldn’t make it ..
regards
Hey guys! I tried to build a customized version of menu… Here’s the result: http://caiocarrara.com.br/home/codeDemo/CustomizedFlyOutMenu/ — It’s working with IE 8 and IE 9.