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
.