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 class="cd-search js-cd-search">
        <input class="reset" type="search" placeholder="Search...">
    </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">
         <ul class="cd-nav__sub-list">
            <li class="cd-nav__sub-item"><a href="#0">My Account</a></li>
            <!-- other list items here -->
</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 -->

        <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 -->
        <!-- other list items here -->
      <!-- other unordered lists here -->

   <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') ) {
    sidebar.insertBefore(searchInput, sidebar.firstChild);
  } else if ( mq == 'desktop' && !Util.hasClass(navList.parentNode, 'js-cd-main-header') ) {
    mainHeader.insertBefore(searchInput, mainHeader.firstChild.nextSibling);
  resizing = false;

function detachElements() {

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

Level up your CSS skills

Each month we email a 1-minute CSS tutorial to 20K developers

Awesome! We just sent you a confirmation link by email

Error - please try again or contact us

Your email address is already subscribed

Project duplicated

Project created

Globals imported

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