News

Create 3D navigation using CSS and Meny.js

Surprising your website visitors with playful 3D interactions is a great way to build a loyal following for your site

3dnavigation

CSS3 has completely revolutionised the way designers create websites, from simple things like rounded corners no longer being rendered as graphics, to complex user interactions. Much of what is possible is still being discovered by web designers – both professionals and novices – and the result is a rich diversity in design approaches and user interface.

In this tutorial we’re going to build a simple website design from a Photoshop mockup, but rather than stick with the original navigation design, we’ll use an open-sourced GitHub-hosted project that uses CSS3 to render our navigation as a 3D element that rotates into view when the mouse moves over the top of the page.
Although the project uses JavaScript, all the user interaction effects arerendered entirely using CSS, so all the benefits of native browser rendering are retained, and it’s also compatible with touch-based devices such as the iPad.

DOWNLOAD TUTORIAL FILES

Mock up your site

We need a design to work with, so we’ve created a simple page mockup inside Photoshop to use as the basis for this tutorial. You can find the PSD file on the resource disc, or use your own design if you prefer. Note the simple navigation bar running along the top of our design.

001 mkdir underscores
 002 cd underscores
 003 wget http://wordpress.org/latest.tar.gz
 004 tar xfz latest.tar.gz

The basic page

We’re rendering our page using several of the new tags found in HTML5. This ensures that our code is semantic (ie it describes its content correctly) and is as lean as possible. Create your basic HTML to match your design, or copy ours from the resource disc, on which you can find the code for this step.

Understanding the markup

You’ll notice that we’ve separated out the two parts of the page so that the menu sits independently from the rest of the page, and a single container has all the content we’ll want to rotate when showing the menu – this is important for the function of the script later on, and helps us achieve the right effect.

001 < div class=”menu”>
 002 < !--The menu will be shown by rotating in 3D space -->
 003 < nav>…>
 004 < /div>
 005 < div class=”container”>
 006 < !-- Everything inside the container will be rotated slightly when the menu is shown -->
 007 < header>…>
 008 < article>…>
 009 < footer>…>
 010 < /div> 

Simple styles

We need to create the basic styles for our page to create the look of our mockup. We’ve already saved a few background images from our mockup to our /styles/ folder where necessary, and we’ll apply these to our design, along with some layout and typographical rules now.

001 body {
 002 background: #1a1a1a;
 003 color: #fff;
 004 font-family: helvetica, arial, 
 sans-serif;
 005 font-size: 62.5%;
 006 line-height: 2.1em;
 007 margin: 0;
 008 padding: 0; 
 009 }
 010 
 011 header, article, footer {
 012 margin: 0;
 013 padding: 0;
 014 display: block;
 015 width: 960px;
 016 margin: auto;
 017 box-shadow: 0px 0px 10px #000;
 018 background: #000;
 019 font-size: 1.2em;
 020 }
 021 
 022 article {
 023 padding-top: 40px;
 024 min-height: 500px;
 025 } 
 026 
 027 article section {
 028 width: 263px;
 029 background: transparent url(boxshine.jpg) repeat-x top left;
 030 min-height: 200px;
 031 border-right: 1px solid #1a1a1a;
 032 float: left;
 033 margin-left: 10px;
 034 padding: 20px;
 035 }
 036 
 037 .lastword {
 038 clear: both;
 039 }
 040 
 041 footer {
 042 padding: 40px;
 043 width: 880px;
 044 color: #999;
 045 }

More CSS

We need to render the logo and introduction text so that it matches our mockup. Firstly, make sure you’ve saved your logo file out of your graphics editor (or use ours on the resource disc), then add the styles shown to hide the < h1> text and replace it with the logo as a background.

001 #logo {
 002 width: 340px;
 003 float: left;
 004 margin-left: 40px;
 005 margin-top: 100px;
 006 margin-right: 40px;
 007 }
 008 
 009 #logo h1 {
 010 width: 320px;
 011 height: 80px;
 012 overflow: hidden;
 013 text-indent: -10000px;
 014 background: transparent url(logo.png) no-repeat top left;
 015 }
 016 
 017 #logo a.calltoaction {
 018 font-size: 0.8em; 
 019 }

Render the menu

One of the most important elements in any page design is the navigation, and our design is no different. We’ve opted for a simple approach because the 3D effect will add enough user interaction without needing to get too elaborate in our design, but it’s essential to render our design carefully.

001 nav {
 002 position: relative;
 003 // add a border to provide a hint to the visitor
 004 // that they can reveal the menu at the 
 top of the page
 005 border-bottom: 2px solid
 #fe9758;
 006 background: #000;
 007 color: #fe9758; 
 008 height: 50px;
 009 display: block; 
 010 box-shadow: 0px 0px 10px #000;
 011 z-index: 1; 
 012 }
 013 
 014 nav ul {
 015 position: relative;
 016 margin: 0;
 017 padding: 0;
 018 text-align: right;
 019 z-index: 100;
 020 background: #000;
 021 padding-right: 100px;
 022 }
 023
 024 nav ul li {
 025 list-style: none;
 026 margin: 0;
 027 padding: 5px 10px;
 028 display: inline-block;
 029 line-height: 35px;
 030 z-index: 100;
 031 }
 032 
 033 nav ul li a {
 034 text-decoration: none;
 035 font-size: 1.2em; 
 036 color: #fe9758;
 037 z-index: 100;
 038 }
 039 
 040 nav ul li a.active, nav ul li a:hover {
 041 color: #fff;

Building a handle

The border we’ve added at the bottom of our navigation bar isn’t yet sufficient to let our visitors know what they need to do, so we’ve added a < div> to our HTML that will become a handle that has an arrow set within. This is all achieved using CSS instead of pre-rendered graphics. Add the code shown to set up the required properties.

001 nav #handle {
 002 width: 20px;
 003 height: 20px;
 004 border-radius: 10px;
 005 position: absolute;
 006 top: 40px;
 007 left: 50%;
 008 margin-left: -10px;
 009 background: #000;
 010 z-index: 1;
 011 }
 012 
 013 nav #handle .downarrow {
 014 border: 5px solid 
 transparent; 
 015 border-top: 8px solid #FE9658;
 016 position: absolute;
 017 left: 5px;
 018 bottom: 0px;
 019 }
 

Add finesse

The design is looking a whole lot closer to the mockup now, but we still need to make some additional design touches, such as the shine behind each section, the subtle dividing lines, and a drop shadow to separate the design from its background. Add the CSS code shown to finalise these aesthetically embellishing design elements, and get closer to the final site.

001 article section {
 002 width: 263px;
 003 background: transparent 
 url(boxshine.jpg) repeat-x top left;
 004 min-height: 200px;
 005 border-right: 1px solid #1a1a1a;
 006 float: left;
 007 margin-left: 10px;
 008 padding: 20px;
 009 }
 010 
 011 header, article, footer {
 012 box-shadow: 0px 0px 10px #000;

Basic layouts

Last but by no means least, the final part of our design that’s missing is the styling of the links. We’ve got two different types of links – calls to action at the bottom of each section inside our main article area, and an inline email link that appears in the final section. Both should be coloured orange to match the design, but the call-to-action links also need some additional styling. Add this now.

001 a {
 002 color: #FE9659;
 003 }
 004 
 005 a.calltoaction {
 006 font-weight: bold;
 007 color: #FE9659;
 008 text-align: right;
 009 text-transform: 
 uppercase;
 010 float: right;
 011 display: block;
 012 cursor: pointer;
 013 }

Test and review

Before going any further, it’s important to ensure your page design is working as you intended in all your target browsers. Load your page in each browser and check that everything is rendering as intended. Correct any issues before moving on as once the script is installed it may be difficult to track down bugs!

Grab the script

We’re going to use an open-source project created by the interactive web developer Hakim El Hattab to create the 3D transition effect in our site design. Start by visiting the GitHub page for the Meny project at github.com/hakimel/meny#meny and read the installation instructions. Download the JavaScript file ready for use.

Include the script

In order to use the Meny system, we need to first include the file we downloaded in the previous step at the top of our page. Inside thesection, add the following code (assuming you saved the JavaScript file into a folder named /scripts/):.

001 // Check viewport width on first load.
 002 if ( $( window ).width() < 450 )
 003 $.fn.smallMenu();
 004 // and:
 005 if ( browserWidth < 450 )

Call the script

Next we need to initialise the script by calling it, and passing in some arguments that will define the parameters we’ll use on our page. This code needs to be called after the elements have been loaded by the browser, so place it immediately before your closing tag to ensure all the HTML has been loaded by the time the code is executed.

001 < script>
 002 // Call the Meny object
 003 var meny = Meny.create({
 004 // pass in a reference to the menu 
 container
 005 menuElement: document.querySelector( '.menu' ),
 006 // and a reference to the container 
 to be rotated
 007 contentsElement: document.
 querySelector( '.container' ),
 008 // tell the script where the menu is located
 009 position: 'top',
 010 // and how many pixels tall the menu is
 011 height: 50
 012 });
 013 

Understanding the options

If you check the code we’ve just used, you’ll see that we set a number of options for the function to determine the containers to be rotated, the height of the menu, and its position. These values are essential to the operation of the effect, and you can find the full details on the project GitHub page, which is once again at github.com/hakimel/meny#meny.using left/right position)

001 var meny = Meny.create({
 002 // The element that will be 
 animated in from off screen
 003 menuElement: document.
 querySelector( '.meny' ),
 004 
 005 // The contents that gets pushed aside while Meny is active
 006 contentsElement: document.
 querySelector( '.contents' ),
 007 
 008 // The alignment of the menu 
 (top/right/bottom/left)
 009 position: 'left',
 010 
 011 // The height of the menu (when 
 using top/bottom position)
 012 height: 200,
 013 
 014 // The width of the menu (when
 015 width: 260

Customise your CSS and script

Although we’ve already set up our styles, if you wanted to make additional changes to the way the effect looks you could use the hooks created by the script. A class is applied to the elements being affected, which allows you to add your own styles. There’s also a JavaScript event generated that you can listen for. Again, documentation can be located on the GitHub page.

001 var meny = Meny.create( ... ) // Initialize as before
 002
 003 meny.addEventListener( 'open', function() {
 004
 005 // do something on open
 006
 007 } );
 008 
 009 meny.addEventListener( 'close', function() 
 010 {
 011 
 012 // do something on close
 013 
 014 } );

Test and review

With your script in place, you need to test across browsers once more to ensure you’re aware of any issues, and the limitations of older browsers that don’t support 3D transformations and/or perspective. Try running your page with JavaScript disabled to see what happens (and make sure you fix any issues with navigation when scripting isn’t available).

Tweak the effect

Finally, now that you’ve got a working effect it’s time to tweak it to your own taste. Make sure that the menu is a good height relative to the size of your navigation element, the handle is big enough to be obvious, and so on. These final tweaks can make all the difference in use.

×