Stretchy Navigation

Stretchy Navigation

A rounded navigation trigger that stretches on click/tap to reveal the navigation items.

Nucleo icons

Sponsored by Nucleo, a free application to collect, customize and export all your icons as icon font and SVG symbols. Made by the CodyHouse folks!

All the resources available on CodyHouse are released under the MIT license. You can support our project with a Paypal donation 🙌

While surfing some Dribbble shots, we came across this nice shopping list concept by Hila Peleg, which inspired today’s resource. We decided to apply a similar idea to a stretching navigation, and create 3 different user cases where this snippet would be useful: 1) fixed navigation, 2) add content button and 3) edit content button.

Icons: Nucleoapp.com

Creating the structure

The HTML structure is pretty basic: a nav.cd-stretchy-nav is used to wrap an unordered list (containing the navigation items) and an a.cd-nav-trigger (for the menu icon).
An additional span.stretchy-nav-bg element is used to create the stretchy background.

<nav class="cd-stretchy-nav">
   <a class="cd-nav-trigger" href="#0">
      Menu
      <span aria-hidden="true"></span>
   </a>

   <ul>
      <li><a href="#0" class="active"><span>Home</span></a></li>
      <li><a href="#0"><span>Portfolio</span></a></li>
      <!-- other list items here -->
   </ul>

   <span aria-hidden="true" class="stretchy-nav-bg"></span>
</nav>

Adding style

We created the .cd-stretchy-nav class to define the main style for the stretchy navigation. We then used two additional classes, .add-content and .edit-content, to customise the toolbars for adding and editing content respectively.

The basic idea of the animation is: we assign to the span.stretchy-nav-bg a fixed height and width (the same of the a.cd-nav-trigger); when the navigation is open, we use the .nav-is-visible class to animate its height (or width, for the .add-content toolbar) to create the stretching effect while revealing the navigation list items.

.cd-stretchy-nav {
  position: fixed;
  z-index: 2;
  top: 40px;
  right: 5%;
}
.cd-stretchy-nav .stretchy-nav-bg {
  /* this is the stretching navigation background */
  position: absolute;
  z-index: 1;
  top: 0;
  right: 0;
  width: 60px;
  height: 60px;
  border-radius: 30px;
  background: #9acd91;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  transition: height 0.2s, box-shadow 0.2s;
}
.cd-stretchy-nav.nav-is-visible .stretchy-nav-bg {
  height: 100%;
  box-shadow: 0 6px 30px rgba(0, 0, 0, 0.2);
}

For the navigation items, we defined 2 different CSS Animations: the scaleIn for the item icons and the slideIn for the item labels; the animation-delay property is then used to animate different children at different moments.

.cd-stretchy-nav ul {
  position: relative;
  z-index: 2;
  visibility: hidden;
  transition: visibility 0.3s;
}
.cd-stretchy-nav ul a {
  position: relative;
}
.cd-stretchy-nav ul a::after {
  /* navigation item icons */
  content: '';
  position: absolute;
  height: 16px;
  width: 16px;
  transform: translateY(-50%) scale(0);
  opacity: .6;
  background: url(../img/cd-sprite-1.svg) no-repeat 0 0;
}
.cd-stretchy-nav ul span {
  /* navigation item labels */
  display: block;
  opacity: 0;
  transform: translateX(-25px);
}

.cd-stretchy-nav.nav-is-visible ul {
  visibility: visible;
}
.cd-stretchy-nav.nav-is-visible ul a::after {
  /* navigation item icons */
  transform: translateY(-50%) scale(1);
  animation: scaleIn 0.15s backwards;
}
.cd-stretchy-nav.nav-is-visible ul span {
  opacity: 1;
  transform: translateX(0);
  animation: slideIn 0.15s backwards;
}

.cd-stretchy-nav.nav-is-visible ul li:first-of-type a::after,
.cd-stretchy-nav.nav-is-visible ul li:first-of-type span {
  animation-delay: 0.05s;
}
/* animation delay for other children here ...*/

@keyframes scaleIn {
  from {
    transform: translateY(-50%) scale(0);
  }
  to {
    transform: translateY(-50%) scale(1);
  }
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateX(-25px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

For the toolbars: when the navigation is open we only display the item icons (using the scaleIn animation), while the item labels are shown when hovering over the navigation (using CSS Transitions).
For the editing toolbar, for example, we have:

.cd-stretchy-nav.edit-content ul span {
  position: absolute;
  top: 0;
  right: 35px;
  height: 30px;
  line-height: 30px;
  opacity: 0;
  visibility: hidden;
  background-color: rgba(0, 0, 0, 0.55);
  transition: opacity 0.2s, visibility 0.2s;
}
.cd-stretchy-nav.edit-content ul span::after {
  /* triangle below the tooltip */
  content: '';
  position: absolute;
  left: 100%;
  top: 50%;
  bottom: auto;
  transform: translateY(-50%);
  height: 0;
  width: 0;
  border: 4px solid transparent;
  border-left-color: rgba(0, 0, 0, 0.55);
}

.no-touch .cd-stretchy-nav.edit-content.nav-is-visible ul a:hover span {
  opacity: 1;
  visibility: visible;
}

Events handling

We used jQuery to listen to the click event on the a.cd-nav-trigger, and add/remove the .nav-is-visible class from the nav.cd-stretchy-nav.

Join our newsletter

Get our monthly recap with the latest CodyHouse news

We use cookies to give you the best possible website experience. By using CodyHouse, you agree to our Privacy Policy.