Animated Navigation with CSS3 Transitions and Transforms

Alt Text

Introduction

This is a continuation of the same techniques used in the previous tutorial: Animated Buttons Using CSS3
We will be using CSS3 transitions and transforms to create a smooth animated navigation with some jQuery to tie it all together. If you are confused on how the CSS3 animation is done please read these resources:

Using CSS3 Transitions, Transforms and Animation
CSS Fundamentals: CSS 3 Transitions
W3Schools: CSS3 transform Property

Important Note: This is only supported in Safari, Chrome, and Firefox 5+ (not yet released), and maybe in IE 10+ (also unreleased)

HTML

This is the basic structure for the navigation. There are 3 major divs within the header. The Header-Shape div holds the shapes that will be animated. The Header-Bar-Container div holds the links and is where the jQuery calculations are made. The Header-Cursor div holds the cursor that will also animate along side the shapes.

	<div id="header">

		<div id="header-shape">	
			<div id="header-shape-triangle">
			</div>
			<div id="header-shape-rect">
			</div>
			<div id="header-shape-circle">
			</div>
		</div>

		<div id="header-bar-container">

			<div id="header-button" class="home current">
				<a href="http://webdesigncrowd.com">WebDesignCrowd</a>
			</div>
			<div id="header-button" class="tutorial">
				<a href="http://webdesigncrowd.com">Tutorials</a>
			</div>
			<div id="header-button" class="search">
				<a href="http://webdesigncrowd.com">Search</a>
			</div>
			<div id="header-button" class="contact">
				<a href="http://webdesigncrowd.com">Contact</a>
			</div>

	    </div>
	   
		<div id="header-cursor">
			<div id="header-cursor-rect">

			</div>
			<div id="header-cursor-triangle">

			</div>
		</div>
	</div>

CSS

Here is the basic css styles for the structure of everything.

#header{
	position: relative;
	padding-top: 10px;
	width: 960px;
}
	#header-cursor{
		width: 50px;
		position: relative;
		top: 5px;
		-webkit-transition: all 0.4s ease;
		-o-transition: all 0.4s ease;
		-moz-transition: all 0.4s ease;
	}
		#header-cursor-rect{
			position: relative;
			height: 5px;
			border-bottom: 1px solid #333;
			background-color: #fff;
			-webkit-transition: all 0.4s ease;
			-o-transition: all 0.4s ease;
			-moz-transition: all 0.4s ease;
		}
		#header-cursor-triangle{
			border-color: transparent transparent #fff transparent;
		    border-style: solid;
		    border-width: 5px;
		    height:0;
		    width:0;
			top: -15px;
			position: relative;
			-webkit-transition: all 0.4s ease;
			-o-transition: all 0.4s ease;
			-moz-transition: all 0.4s ease;
		}
#header-bar-container{
	position: relative;
	height: 35px;
}
	#header-button{
		float: left;
		position: relative;
		font-size: 23px;
		line-height: 23px;
		font-weight: bold;
		color: #ddd;
		height: 35px;
		margin-left: 20px;
		text-shadow:1px 1px 1px #111;
	}
		#header-button.home{
                /*Reserved for optional additional customization*/
		}
		#header-button.tutorial{
                /*Reserved for optional additional customization*/
		}
		#header-button.search{
                /*Reserved for optional additional customization*/
		}
		#header-button.contact{
                /*Reserved for optional additional customization*/
		}
		#header-button.current a{
			color: #7FD13D;
		}
			#header-shape{
				position: relative;
				width: 40px;
				height: 50px;
				top: -18px;
				-webkit-transition: all 0.4s ease;
				-o-transition: all 0.4s ease;
				-moz-transition: all 0.4s ease;
			}
				#header-shape-rect{
					position: relative;
					height: 20px;
					width: 26px;
					background-color: #fff;
					-webkit-transition: all 0.4s ease;
					-o-transition: all 0.4s ease;
					-moz-transition: all 0.4s ease;
					left: 7px;
				}
				#header-shape-triangle{
					z-index: 1;
					position: relative;
					border-color: transparent transparent #fff transparent;
				    border-style: solid;
				    border-width: 20px;
				    height:0;
				    width:0;
					-webkit-transition: all 0.4s ease;
					-o-transition: all 0.4s ease;
					-moz-transition: all 0.4s ease;
				}
				#header-shape-circle{
					z-index: 2;
					position: relative;
					margin: auto;
					top:-35px;
					width: 10px;
					height: 10px;
					background: #fff;
					-webkit-border-radius: 5px;
					-moz-border-radius: 5px;
					border-radius: 5px;
					-webkit-transition: all 0.4s ease;
					-o-transition: all 0.4s ease;
					-moz-transition: all 0.4s ease;
				}
				#header-shape-circle{
					position: relative;
					margin: auto;
					top:-35px;
					width: 10px;
					height: 10px;
					background: #fff;
					-webkit-border-radius: 5px;
					-moz-border-radius: 5px;
					border-radius: 5px;
					-webkit-transition: all 0.4s ease;
					-o-transition: all 0.4s ease;
					-moz-transition: all 0.4s ease;
				}

The next portion of css is the transforms and changes to the shapes that the transitions will animate.

		/* Animations */
		
		.tut-rotate{
			-webkit-transform: rotateZ(225deg) translateY(-3px) translateX(-17px);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		.tut-skinny{
			-webkit-transform: scaleX(.3) scaleY(2.5);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		#header-shape-triangle.tut-brush{
			border-width: 10px;
			-webkit-transform: translateY(-20px) translateX(10px) scaleY(2);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		.tut-circle{
			-webkit-transform: scale(1.83);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		
		.search-rotate{
			-webkit-transform: rotateZ(45deg) translateY(-5px) translateX(15px);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		.search-skinny{
			-webkit-transform: scaleX(.3) scaleY(2.5);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		#header-shape-triangle.search-triangle{
			width: 0px;
			height: 0px;
			border-color: #fff;
			border-width: 15px;
			-webkit-border-radius: 15px;
			-moz-border-radius: 20px;
			border-radius: 20px;
			-webkit-transform: translateY(10px) translateX(4px);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		#header-shape-circle.search-circle{
			background-color: #ddd;
			-webkit-transform: scale(2.5) translateY(2px) translateX(-1px);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		
		#header-shape-triangle.contact-rotate{
			border-width: 13px;
			border-color: transparent transparent #ddd transparent;
			-webkit-transform: rotateZ(-180deg) translateY(-26px) translateX(-7px);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}
		#header-shape-circle.contact-circle{
			background-color: #ddd;
			-webkit-transform: scale(.5) translateY(25px);
		    -moz-transform: rotateZ(-135deg) translateX(0px);
		    transform: rotateZ(-135deg) translateX(0px);
		}

jQuery

This jQuery is a little more complex than the last one because of the added cursor animation. I wanted it to expand the width to fit the same width as the selected button in the navigation. And when you stop hovering, I wanted the cursor and the shape to animate back to the original state.

This first portion of the script calculates the width and height and offset position of the current div which is where the animations would revert to. It then animates the cursor and the shapes to the current div. This current div can be changed by giving the extra class “current” to the desired button. Next I defined two important functions. One function resets the shape so the animations will fire correctly. The second function determines the animation to revert to the current div.

	var currDiv = $('#header-button.current');
	var currPosition = currDiv.position();
	var currWidth = currDiv.width();
	$('#header-cursor').css({left: currPosition.left + 20, width: currWidth});
	$('#header-cursor-triangle').css({left: (currWidth / 2) - 4.5});
	$('#header-shape').css({left: currPosition.left + ((currWidth / 2))});
	
	function shapeReset() {
		$('#header-shape').removeClass();
		$('#header-shape-rect').removeClass();
		$('#header-shape-triangle').removeClass();
		$('#header-shape-circle').removeClass();
	}
	
	function currShape() {
		if ($('#header-button.current.home').length) {
			shapeReset();
		}
		else if ($('#header-button.current.tutorial').length) {
			shapeReset();
			$('#header-shape').addClass('tut-rotate');
			$('#header-shape-rect').addClass('tut-skinny');
			$('#header-shape-triangle').addClass('tut-brush');
			$('#header-shape-circle').addClass('tut-circle');
		}
		else if ($('#header-button.current.search').length) {
			shapeReset();
			$('#header-shape').addClass('search-rotate');
			$('#header-shape-rect').addClass('search-skinny');
			$('#header-shape-triangle').addClass('search-triangle');
			$('#header-shape-circle').addClass('search-circle');
		}
		else if ($('#header-button.current.contact').length) {
			shapeReset();
			$('#header-shape-triangle').addClass('contact-rotate');
			$('#header-shape-circle').addClass('contact-circle');
		}
	}
	
	currShape();

The rest of the script is simply hooking up the animations to fire on hover and resetting the shapes as it animates between different buttons.

	$('#header-button.home, #header-button.tutorial, #header-button.search, #header-button.contact').hover(
			  function () {
				var btnPosition = $(this).position();
				var btnWidth = $(this).width();
			    $('#header-cursor').css({left: btnPosition.left + 20, width: btnWidth});
				$('#header-cursor-triangle').css({left: (btnWidth / 2) - 4.5});
				$('#header-shape').css({left: btnPosition.left + ((btnWidth / 2))});
			  }, 
			  function () {
				$('#header-cursor').css({left: currPosition.left + 20, width: currWidth});
				$('#header-cursor-triangle').css({left: (currWidth / 2) - 4.5});
				$('#header-shape').css({left: currPosition.left + ((currWidth / 2))});
				currShape();
			  }
	);
	$('#header-button.home').hover(
			  function () {
				shapeReset();
			  }, 
			  function () {	
			  }
	);
	$('#header-button.tutorial').hover(
			  function () {
				shapeReset();
				$('#header-shape').addClass('tut-rotate');
				$('#header-shape-rect').addClass('tut-skinny');
				$('#header-shape-triangle').addClass('tut-brush');
				$('#header-shape-circle').addClass('tut-circle');
			  }, 
			  function () {		
			  }
	);
	$('#header-button.search').hover(
			  function () {
				shapeReset();
				$('#header-shape').addClass('search-rotate');
				$('#header-shape-rect').addClass('search-skinny');
				$('#header-shape-triangle').addClass('search-triangle');
				$('#header-shape-circle').addClass('search-circle');
			  }, 
			  function () {			
			  }
	);
	$('#header-button.contact').hover(
			  function () {
				shapeReset();
				$('#header-shape-triangle').addClass('contact-rotate');
				$('#header-shape-circle').addClass('contact-circle');
			  }, 
			  function () {
			  }
	);