CodyHouse Framework + Components are featured on Product Hunt! Join the discussion →

Responsive Sidebar Navigation

Responsive Sidebar Navigation

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

Nucleo logo Sponsored by Nucleo, a powerful icon manager for web designers

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

👉 Important: this experiment is built using the CodyHouse Framework.

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

💌 Join our newsletter

Be the first to know when we ship something cool!

Project duplicated.