Go to homepage

Projects /

Responsive Sidebar Navigation

An easy-to-integrate side, vertical navigation, ideal for dashboards and admin areas.

Responsive Sidebar Navigation
Check our new component library →

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 ;)

👋 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).

Project duplicated

Project created

Globals imported

There was an error while trying to export your project. Please try again or contact us.