Go to homepage

Projects /

Full-Screen Pop-Out Navigation

Here is a fixed menu that drives users' attention to a couple of call-to-action buttons first, then let them explore the full-screen navigation.

Full-Screen Pop-Out Navigation
Check our new component library →

It's becoming a common approach to hide the navigation, make it accessible after a click on the menu link. "One click more than necessary" some of you may argue. It really depends by the specific case IMO. I mean Amazon could never hide the entire navigation on a big device. But if you have a website with a relatively modest quantity of content, a huge menu with few important call-to-action buttons, it makes sense to drive the user's attention to those buttons first, then let her/him explore the rest.

One step further is to make the header - therefore the menu link - always accessible. We already suggested a new approach to achieve that. Today we take inspiration from how Medium reveals the header when you change your scrolling direction - from down to up. Quite smart!

Image credits: Unsplash.

Creating the structure

We created a <header> element to wrap the logo, the secondary navigation (login/signup) and the trigger for the primary navigation (.cd-primary-nav-trigger). The primary navigation is outside the header, which makes it easier for us to handle the CSS transformation effects. Both primary and secondary navigations are unordered lists semantically wrapped into a <nav> element.

<header class="cd-header">
   <div class="cd-logo"><!-- ... --></div>

      <ul class="cd-secondary-nav">
         <li><a href="#0">Log In</a></li>
         <li><a href="#0">Register</a></li>
   </nav> <!-- cd-nav -->

   <a class="cd-primary-nav-trigger" href="#0">
      <span class="cd-menu-text">Menu</span><span class="cd-menu-icon"></span>
   </a> <!-- cd-primary-nav-trigger -->

   <ul class="cd-primary-nav">
      <li class="cd-label">About us</li>
      <li><a href="#0">The team</a></li>
      <li><a href="#0">Our services</a></li>
      <li><a href="#0">Our projects</a></li>
      <li><!-- ... --></li>

   <!-- content -->

Adding style

First of all, to create the slide-in effect of the primary navigation we use a combo of CSS3 transitions and transformations. By default the navigation is hidden by pushing it right above the viewport (translateY(-100%)). When the user clicks on the trigger element (.cd-primary-nav-trigger), we use jQuery to add the .is-visible class to the navigation. The transition applied to the transform property smooths the movement.

.cd-primary-nav {
  /* by default it's hidden - on top of the viewport */
  position: fixed;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  transform: translateY(-100%);
  transition-property: transform;
  transition-duration: 0.4s;

.cd-primary-nav.is-visible {
  transform: translateY(0);

For the header slide-in effect - activated when the user changes the scrolling direction from down to up - we needed to create some classes and handle them through jQuery. By default the header is in absolute position: that means that it scrolls with the content (it's in absolute position so we can place it on top of the background-image). As soon as the header is no longer visible, we give it a .is-fixed class, thus changing its position from absolute to fixed, and placing it right above the viewport (top: -80px). As the user scrolls up, the header gets back: we give it the .is-visible class, this way we move it down along the Y axis (translate3d(0, 100%, 0)).

.cd-header {
  position: absolute;
  top: 0;
  left: 0;
  background: transparent;
  height: 80px;
  width: 100%;
  transition: background-color 0.3s;

.cd-header.is-fixed {
  /* when the user scrolls down, we hide the header right above the viewport */
  position: fixed;
  top: -80px;
  background-color: rgba(2, 23, 37, 0.96);
  transition: transform 0.3s;

.cd-header.is-visible {
  /* if the user changes the scrolling direction, we show the header */
  transform: translate3d(0, 100%, 0);

Events handling

When user starts scrolling, we need to detect if he's scrolling up or down, and add/remove classes to the primary navigation accordingly :

      previousTop: 0
   function () {
      var currentTop = $(window).scrollTop();
      //check if user is scrolling up
      if (currentTop < this.previousTop ) {
         //if scrolling up...
         //add class 'is-visible' to the main navigation
         //if currentTop == 0, remove 'is-fixed' and 'is-visible' classes 
      } else {
         //if scrolling down...
         //add the 'is-fixed' class to the main navigation as soon as it is no longer visible
         //add class 'is-visible' to the main navigation
      //set previousTop for the next iteration
      this.previousTop = currentTop;

The header slide-in effect has been implemented only when the viewport is larger than 1170px (the MQL variable has been defined in the .js file). iOS devices, in fact, freeze the DOM manipulation during scrolling, so functions are executed only at the end of the scrolling (we couldn't find a bug report, but here is what jQueryMobile says).

Project duplicated

Project created

Globals imported

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