Go to homepage

Projects /

Secondary Sliding Navigation

A bold, secondary menu that slides over the main navigation.

Secondary Sliding Navigation
Check our new component library →

Today’s resource is a simple, handy snippet: a secondary navigation that slides down, replacing the main navigation links.

This approach can be an alternative to a standard dropdown menu, in particular if you want to emphasise more the sub navigation. Besides you can easily customize the snippet and use the slide in panel for a search box instead, or a login form - just to give you a couple of ideas.

Creating the structure

The HTML is structured in 2 main elements: an <header> wrapping the main navigation, and a <main> containing the page content.
The main navigation is composed of 2 nested unordered lists, semantically wrapped in a <nav> element.

<header>
   <div class="cd-logo"><a href="#0"><img src="img/cd-logo.svg" alt="Logo"></a></div>

   <nav class="cd-main-nav-wrapper">
      <ul class="cd-main-nav">
         <li><a href="#0">About</a></li>
         <!-- other list items here -->
         <li>
            <a href="#0" class="cd-subnav-trigger"><span>Categories</span></a>
            <ul>
               <li class="go-back"><a href="#0">Menu</a></li>
               <li><a href="#0">Category 1</a></li>
               <!-- other list items here -->
            </ul>
         </li>
      </ul>
   </nav> 

   <a href="#0" class="cd-nav-trigger">Menu<span></span></a>
</header>

<main class="cd-main-content">
   <!-- main content here -->
</main>

Adding style

On small devices, the main navigation is on the right side, hidden by default; when user clicks the menu icon, the <main> and <header> elements translate to the left (nav-is-visible class is applied) to reveal the navigation.
When user clicks the .cd-subnav-trigger, the main navigation is pushed to the left and replaced by the secondary navigation.

header.nav-is-visible {
  transform: translateX(-260px);
}
.cd-main-content.nav-is-visible {
  transform: translateX(-260px);
}
.cd-main-nav {
  position: fixed;
  top: 0;
  right: 0;
  width: 260px;
  visibility: hidden;
}
.cd-main-nav.nav-is-visible {
  visibility: visible;
}
.cd-main-nav li ul {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  transform: translateX(260px);
}
.cd-main-nav.moves-out > li > a {
  /* push the navigation items to the left - and lower down opacity - when secondary nav slides in */
  transform: translateX(-100%);
  opacity: 0;
}
.cd-main-nav.moves-out > li > ul {
  /* reveal secondary nav */
  transform: translateX(0);
}

On desktop devices (viewport width more than 1024px), the secondary navigation is placed on top of the header (outside the viewport) and slides in covering the main navigation. We assigned a higher z-index to the .cd-logo and .cd-subnav-trigger so that they remain visible after the sub navigation has slided in.
Besides, we assigned the sub navigation the same padding as the .cd-main-nav  and inserted a .placeholder element as last list item occupying the same space of the .cd-subnav-trigger: this way we make sure the sub navigation list items don't cover both the logo and the .cd-subnav-trigger.

@media only screen and (min-width: 1024px) {
  .cd-main-nav {
    height: 80px;
    /* padding left = logo size + logo left position*/
    padding: 0 5% 0 calc(5% + 124px);
    text-align: right;
  }
  .cd-main-nav li ul {
    height: 80px;
    background-color: #7e4d7e;
    /* padding left = logo size + logo left position*/
    padding: 0 5% 0 calc(5% + 124px);
    transform: translateY(-80px);
    transition: transform 0.3s 0.2s;
  }
  .cd-main-nav li ul li {
    opacity: 0;
    transform: translateY(-20px);
    transition: transform 0.3s 0s, opacity 0.3s 0s;
  }
  .cd-main-nav .placeholder {
    /* never visible or clickable- it is used to take up the same space as the .cd-subnav-trigger */
    display: block;
    visibility: hidden;
    opacity: 0;
    pointer-event: none;
  }
  .cd-main-nav.moves-out > li > ul {
    transition: transform 0.3s;
    transform: translateY(0);
  }
  .cd-main-nav.moves-out > li ul li {
    opacity: 1;
    transform: translateY(0);
    transition: transform 0.3s 0.2s, opacity 0.3s 0.2s;
  }
}

Events handling

We used jQuery to add/remove classes according to specific events.
The only important thing to note is that in the starting HTML structure the navigation is inside the <header>. On mobile, we wanted the navigation to be on the side, hidden by default, and it was easier for us to have it outside the header. So we use jQuery to move the navigation outside the header on small devices.

Project duplicated

Project created

Globals imported

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