Building responsive navigations for mega sites is never an easy task. If you’re working on an admin panel, chances are you’ll need to design and develop a vertical menu, with plenty of sub-categories. That’s why we decided to share today's snippet! Our Sidebar navigation can make your life easier by providing a starting, simple template for your next project ;)
- ⭐️ Icons: Nucleo, icon organizer & icon library
👋 A new version of this component is available. Download now →.
Creating the structure
The HTML structure is composed by 2 main elements: a <header>
element, containing the website logo, the search form, the navigation trigger (.cd-nav-trigger
- mobile version only) and the top navigation, and a <main>
element containing the page main content (div.content-wrapper
) and the sidebar navigation (nav.cd-side-nav
).
<header class="cd-main-header js-cd-main-header">
<div class="cd-logo-wrapper">
<a href="#0" class="cd-logo"><img src="assets/img/cd-logo.svg" alt="Logo"></a>
</div>
<div class="cd-search js-cd-search">
<form>
<input class="reset" type="search" placeholder="Search...">
</form>
</div> <!-- cd-search -->
<button class="reset cd-nav-trigger js-cd-nav-trigger" aria-label="Toggle menu"><span></span></button>
<ul class="cd-nav__list js-cd-nav__list">
<li class="cd-nav__item"><a href="#0">Tour</a></li>
<li class="cd-nav__item"><a href="#0">Support</a></li>
<li class="cd-nav__item cd-nav__item--has-children cd-nav__item--account js-cd-item--has-children">
<a href="#0">
<img src="assets/img/cd-avatar.svg" alt="avatar">
<span>Account</span>
</a>
<ul class="cd-nav__sub-list">
<li class="cd-nav__sub-item"><a href="#0">My Account</a></li>
<!-- other list items here -->
</ul>
</li>
</ul>
</header> <!-- .cd-main-header -->
<main class="cd-main-content">
<nav class="cd-side-nav js-cd-side-nav">
<ul class="cd-side__list js-cd-side__list">
<li class="cd-side__label"><span>Main</span></li>
<li class="cd-side__item cd-side__item--has-children cd-side__item--overview js-cd-item--has-children">
<a href="#0">Overview</a>
<ul class="cd-side__sub-list">
<li class="cd-side__sub-item"><a href="#0">All Data</a></li>
<!-- other list items here -->
</ul>
</li>
<li class="cd-side__item cd-side__item--has-children cd-side__item--notifications cd-side__item--selected js-cd-item--has-children">
<a href="#0">Notifications<span class="cd-count">3</span></a>
<ul class="cd-side__sub-list">
<li class="cd-side__sub-item"><a href="#0">All Notifications</a></li>
<!-- other list items here -->
</ul>
</li>
<!-- other list items here -->
</ul>
<!-- other unordered lists here -->
</nav>
<div class="cd-content-wrapper">
<!-- main content here -->
</div> <!-- .cd-content-wrapper -->
</main> <!-- .cd-main-content -->
In the initial HTML structure, the .cd-search
and .cd-nav__list
elements are inside the <header>
, while on mobile devices they are moved inside the .cd-side-nav
element (more in the Events Handling section).
Adding style
We created 2 different sidebar configurations, according to the screen size.
On small devices, the sidebar has a 100% width, is in absolute position and hidden by default (visibility: hidden
). When the user clicks/taps the .cd-nav-trigger
, the sidebar visibility is changed to visible (using the .cd-side-nav--is-visible
class).
.cd-side-nav {
position: absolute;
z-index: var(--zindex-header);
left: 0;
top: var(--cd-header-height);
width: var(--cd-sidebar-width);
transition: .2s;
visibility: hidden;
opacity: 0;
}
.cd-side-nav--is-visible {
opacity: 1;
visibility: visible;
}
On bigger devices (viewport bigger than 1024px), the expanded version of the sidebar is shown.
Events handling
By default, the .cd-search
and .cd-nav__list
elements are inside the <header>
.
On small devices (viewport smaller than 1024px), we move these elements inside the .cd-side-nav
navigation.
//on resize, move search and top nav position according to window width
var resizing = false;
window.addEventListener('resize', function(){
if(resizing) return;
resizing = true;
(!window.requestAnimationFrame) ? setTimeout(moveNavigation, 300) : window.requestAnimationFrame(moveNavigation);
});
window.dispatchEvent(new Event('resize'));//trigger the moveNavigation function
function moveNavigation(){
var mq = checkMQ();
if ( mq == 'mobile' && !Util.hasClass(navList.parentNode, 'js-cd-side-nav') ) {
detachElements();
sidebar.appendChild(navList);
sidebar.insertBefore(searchInput, sidebar.firstChild);
} else if ( mq == 'desktop' && !Util.hasClass(navList.parentNode, 'js-cd-main-header') ) {
detachElements();
mainHeader.appendChild(navList);
mainHeader.insertBefore(searchInput, mainHeader.firstChild.nextSibling);
}
resizing = false;
};
function detachElements() {
searchInput.parentNode.removeChild(searchInput);
navList.parentNode.removeChild(navList);
};
Besides, we integrated a Vanilla JS modified version of the jQuery-menu-aim plugin to differentiate between users trying to hover over a sidebar item and user trying to navigate into a submenu’s contents (desktop version only).