Today’s resource is a strong approach to showing a website navigation. Bear in mind, though, it doesn’t have to be the “main” navigation. You could have, for example, a product gallery and you’d like to create a smooth transition while switching from one product category to the other.

To increase the focus on the menu, we pushed the main content along the z-axis (by using CSS transformations we actually scale down the content size, we don’t use 3D translations, but the result is the same).

The interesting bit: when you select a new category, we switch the content in the background, then move it back to the original position, hiding the navigation.

Now let’s dive into the code!

Inpiration: chulakov.com.

The icons used in the demo are from our Nucleo icons application.

👋 A new version of this component is available. Download now →.

Creating the structure

The HTML is structured in 3 main elements: a .cd-nav-trigger used to create the menu icon, a .cd-section element containing the page main content and a .cd-nav-container for the main navigation.

<a href="#cd-nav" class="cd-nav-trigger"> Menu<span><!-- used to create the menu icon --></span> </a> <!-- .cd-nav-trigger --> <main> <section class="cd-section index cd-selected"> <header> <div class="cd-title"> <h2><!-- title here --></h2> <p><!-- brief description here --></p> </div> <!-- .cd-title --> </header> <div class="cd-content"> <!-- your content here --> </div> </section> <!-- .cd-section --> </main> <nav class="cd-nav-container" id="cd-nav"> <header> <h3>Navigation</h3> <a href="#0" class="cd-close-nav">Close</a> </header> <ul class="cd-nav"> <li class="cd-selected" data-menu="index"> <a href="index.html"> <span> <!-- svg icon here --> </span> <em><!-- title here --></em> </a> </li> <li data-menu="projects"> <!-- .... --> </li> <!-- other list items here --> </ul> <!-- .cd-3d-nav --> </nav>

An additional div.cd-overlay has been used to create a shadow layer, visible only when navigation is active.

Adding style

To realise our animation, we used CSS3 Transformations applied to the <main> and <nav> elements.

By default, the navigation has a position fixed and is translated to the right, outside the viewport ( translateX(100%) ). When user clicks the menu icon, the class .is-visible is added to the <nav> element which is moved back into the viewport ( translateX(0) ), while the .scale-down class is added to the <main> element to scale it down ( scale(.9) ). And of course we have used CSS3 Transitions to achieve a smooth animation!

.cd-nav-container { position: fixed; top: 0; right: 0; width: 80%; height: 100%; transform: translateX(100%); transition: transform 0.4s; } .cd-nav-container.is-visible { transform: translateX(0); } main { transition: transform 0.4s; } main.scale-down { transform: scale(0.9); }

When user selects an item from the navigation, a new .cd-section element is created and inserted in the DOM (more details in the 'Events handling' section).

The .cd-selected class is then assigned to this new inserted .cd-section element, while it is removed from the old .cd-section (the content originally visible in the page). This way the new section element (which is initially translated to the right, outside the viewport) is moved back ( translateX(0) ), covering the old content ( z-index: 2 ).

One note: during this animation you don't see the old section moving to the right ( translateX(100%) ) because we set a delay for the .cd-section transition on transformations (it will move after .4s).

.cd-section { position: absolute; z-index: 1; top: 0; left: 0; height: 100%; width: 100%; overflow-y: auto; transform: translateX(100%); transition: transform 0s 0.4s; } .cd-section.cd-selected { position: relative; z-index: 2; transform: translateX(0); transition: transform 0.4s 0s; }

Events handling

The index.html file contains only the 'Intro' content. A different html file has been created for each section (projects.html, careers.html, ..) with exactly the same structure, but with different .cd-section content.

When user selects a new item from the navigation, a new <section> element is created and inserted in the DOM ( loadNewContent function).

The load() function is then used to load the specific section content (we used a data-menu attribute assigned to the navigation list item to determine the file content to be loaded).

Once the new html content has been inserted, we assign the .cd-selected class to the new section and close the navigation.

$('.cd-nav li').on('click', function(event){ event.preventDefault(); var target = $(this), //detect which section user has chosen sectionTarget = target.data('menu'); if( !target.hasClass('cd-selected') ) { //if user has selected a section different from the one alredy visible //update the navigation -> assign the .cd-selected class to the selected item target.addClass('cd-selected').siblings('.cd-selected').removeClass('cd-selected'); //load the new section loadNewContent(sectionTarget); } else { // otherwise close navigation toggleNav(false); } }); function loadNewContent(newSection) { //create a new section element and insert it into the DOM var section = $('<section class="cd-section '+newSection+'"></section>').appendTo($('main')); //load the new content from the proper html file section.load(newSection+'.html .cd-section > *', function(event){ //add the .cd-selected to the new section element -> it will cover the old one section.addClass('cd-selected').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){ //close navigation toggleNav(false); }); section.prev('.cd-selected').removeClass('cd-selected'); }); $('main').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){ //once the navigation is closed, remove the old section from the DOM section.prev('.cd-section').remove(); }); if( $('.no-csstransitions').length > 0 ) { //detect if browser supports transitions toggleNav(false); section.prev('.cd-section').remove(); } }

One note: we implemented a simple load() function to upload the new html content, but you may wanna replace it with a proper $.ajax call in order to proper handle errors, beforeSend request etc. according to your project.