Awesome Cufonized Fly-out Menu with jQuery and CSS3

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 […]
flyoutmenu

From our sponsor: Design every part of your website with the Divi Theme Builder.

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!

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!

Tagged with:

Mary Lou

ML is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

http://www.codrops.com

Stay up to date with the latest web design and development news and relevant updates from Codrops.

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.

Feedback 115

Comments are closed.
  1. How can I get it to stay hovering on the current page, instead of returning to the top of the list?

  2. * the first item in the menu,
    * which is selected by default
    var $selected = $menu.find(‘li:first’);

    Can anyone tell me how select a different menu item by default?

  3. I can get it to eventually hover on the selected page by changing this:

    var $selected = $menu.find(‘li:first’);

    to this:

    var $selected = $menu.find(‘#thispage’);

    and putting id=”thispage” on the li for the page like

    Services

    However, it only works once I’ve moused over the menu. When it first loads, it’s still hovering over the first element. I’m still digging to try to find where the draw is initialized on page load.

  4. Great! I’ve tried to change the active status, but it doesn’t work. How can I do?

    .slidingMenu li a:active {
    text-transform:lowercase;
    }

  5. Alright, I’ve got it holding an active status appropriately. The necessary changes are listed below.

    This part will tell the script which menu item to make active. For the example menu, if you wanted to make “Portfolio” the active item, you would have to add an id = “thispage” to the list item like this:

    “09 Portfolio

    This script change makes the script recognize the item which has been made active, instead of just keeping the first item active.
    In the script, change:
    “05 /**
    06 * the first item in the menu,
    07 * which is selected by default
    08 */
    09 var $selected = $menu.find(‘li:first’);”

    to this:
    “05 /* select menu item with id = “thispage” */
    06 var $selected = $menu.find(‘#thispage’);”

    This next part is kind of odd. Setting the top position for the selected element wasn’t working in the code. A good bit of debugging never made it obvious why the original placement for the code didn’t work.
    In the script, change this:
    “/**
    12 * this is the absolute element,
    13 * that is going to move across the menu items
    14 * It has the width of the selected item
    15 * and the top is the distance from the item to the top
    16 */
    17 var $moving = $(”,{
    18 className : ‘move’,
    19 top : $selected[0].offsetTop + ‘px’,
    20 width : $selected[0].offsetWidth + ‘px’
    21 });”

    to this:
    ” /**
    12 * this is the absolute element,
    13 * that is going to move across the menu items
    14 * It has the width of the selected item
    15 * and the top is the distance from the item to the top
    16 */
    17 var $moving = $(”,{
    18 className : ‘move’,
    19 top : $selected[0].offsetTop + ‘px’, /* <– this doesn't work */
    20 width : $selected[0].offsetWidth + 'px'
    21 });
    22
    23 $moving.css('top',$selected[0].offsetTop + 'px'); /* <– this fixes the problem */"

    Hopefully I've caught all of the changes and the formatting of the comment section keeps the code changes mostly intact.

  6. Ahh, forgot about the html being accepted in comments. The Portfolio item with the id should look like this

    “09 [li id = “thispage”][a href=”#”]Portfolio[/a][/li]”

    with the square brackets swapped out for the > & < as appropriate in html.

  7. Brian: in .slidingMenu
    change changing the position to relative… and maybe top:0px etc to fit the div…

    thanks Mary for the tutorial 🙂

  8. Hi Mary Lou,

    Awesome template. Is there any way to make it “sticky” and incorporate submenus? I.e. when user clicks portfolio category on right, then left menu slides in, remains on screen & displays still life, painting, etc subcategories for user to select.

    Thanks in advance!!!

  9. Ok, managed to get this menu working in a div width. I am just experiencing one weird effect and that is the description div flying out too far and overlapping the menu div. Who has the solution for this problem. i hope someone can help me thanks

  10. Currently I don’t know who the blessed person is who created this wonderful and honestly trivial but indeed creative demo, but I throw over some *hugs*!

    Btw folks: I got it working in ie7-9 including umlauts.

    For your interest you should update cufon-yui to 1.09i which makes the fonts work with ie9.

    Have a nice day!
    Best wishes
    Fernandos

  11. Hello,

    Thank you for this great job!
    Is it possible to work with IE6 and later?

    And somebody found solution to work with a separate gallery or slideshow that was posted also above by ROSS?

    Thank you!

  12. Hello,

    I can’t solve to change the activate status of the menu.
    Can told me somebody an easy way. I tried that LEIGH wrote but it’s not working.

  13. Great tutorial – I love it and am using it.
    I have one minor problem that I wonder if you could help with:
    When I click on the link and go to another page and then use the back button to go back, the slide out description bar is still there and will not return and hide until I mouse over and mouse out of the original link. Is there a way to have it return when I return to the original page or did I mess up somewhere?
    Thank again!

  14. is there a way i can un’cufonize this so i can use google fonts instead? it’s a really brilliant piece of code && i’ve managed to customize everything but the menu fonts // it’s live here :: http://bkpkr.info/new

    cheers !! (:

  15. I have been trying to make this work with IE7 but am stuck. I read FernandoS has it working on ie7-9, can you please provide me with some advice?
    Thanks, I love the effect, it looks amazing in FF and Chrome

  16. Hello,

    I’m amazed by this tutorial!
    I’ve been after one like this for months!

    I just have a quick question.
    How do i set the “slidingMenuDesc” menus to stop after sliding out, and be used as a page, so i could add an image gallery or proper contact page etc?

    Any help would be much appreciated!

    Thank you