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.