Sometimes you just want your website navigation to be bold. Design agencies, for example, use their portfolio to show off their skills and push a little usability standards.
Another good example is mobile apps: animated elements are key ingredients of the user experience. In this case a 3D menu can't just be fun. It has to be efficient.
Inspiration for this nugget came from Taasky, a to-do iOS app with a great side navigation - that you can see in action on dribbble.
⭐️ Icons: Nucleo, icon organizer & icon library
👋 Important: this experiment is built using the CodyHouse Framework.
Creating the structure
We created a <header>
element to wrap the logo and the trigger for the rotating navigation (.cd-header__nav-trigger
) and a <main>
element to wrap the main content.
We used an unordered list for the navigation, semantically wrapped into a <nav>
element. A span.cd-3d-nav__marker
has been appended to the <nav>
to create the marker for the selected item in the navigation.
<header class="cd-header container flex justify-between items-center">
<a href="#0" class="cd-logo">
<!-- logo here -->
</a>
<a href="#cd-3d-nav" class="cd-header__nav-trigger" aria-label="Toggle menu">
<span aria-hidden="true"></span>
</a>
</header>
<main class="cd-main">
<!-- all your content here -->
</main>
<nav class="cd-3d-nav js-cd-3d-nav" id="cd-3d-nav">
<ul class="cd-3d-nav__list">
<li class="cd-3d-nav__item cd-3d-nav__item--selected">
<a href="#0">
<svg aria-hidden="true" class="icon icon--md"><g stroke="currentColor" stroke-width="2" fill="none"><path d="M12,6.6c1.2-0.5,2.6-0.8,4-0.8 c5.6,0,10.2,4.6,10.2,10.2"></path><path d="M5.8,16c0-1.4,0.3-2.8,0.8-4"></path><line x1="13.9" y1="13.9" x2="8.4" y2="8.4"></line> <circle cx="16" cy="16" r="15"></circle><circle cx="16" cy="16" r="3"></circle></svg>
<span>Dashboard</span>
</a>
</li>
<!-- other list items here -->
</ul>
<span class="cd-3d-nav__marker cd-3d-nav__marker--col-1" aria-hidden="true"></span>
</nav>
Adding Style
To realise our animation, we used CSS3 Transformations applied to the <header>
, <main>
and <nav>
elements.
Here is a quick preview to show you the animation process (.gif created in After Effects).
By default, the navigation (.cd-3d-nav
) is hidden right above the viewport (translateY(-100%)
and visibility: hidden
), while the unordered list (.cd-3d-nav__list
) is rotated (rotateX(90deg)
and transform-origin: bottom center
).
When user clicks the trigger element, the class .cd-main--is-translated
is added to the <main>
, .cd-header--is-translated
to the <header>
and .cd-3d-nav--is-visible
to the <nav>
. These classes translate the elements of a quantity equal to the navigation height, while the .cd-3d-nav__list
is rotated back (rotateX(0)
).
CSS3 Transitions have been used to achieve a smooth animation.
:root {
/* nav */
--cd-nav-height: 80px;
/* animation */
--cd-nav-animation: 0.5s;
}
.cd-header {
transition: transform var(--cd-nav-animation);
}
.cd-header--is-translated {
transform: translateY(var(--cd-nav-height));
}
.cd-3d-nav {
position: fixed;
top: 0;
left: 0;
visibility: hidden;
perspective: 1000px; /* enable a 3D-space for children elements */
transform: translateY(-100%);
transition: transform var(--cd-nav-animation) 0s, visibility 0s var(--cd-nav-animation);
}
.cd-3d-nav--is-visible {
visibility: visible;
transform: translateY(0);
transition: transform var(--cd-nav-animation) 0s, visibility var(--cd-nav-animation) 0s;
}
.cd-3d-nav__list {
transform-origin: center bottom;
transform: rotateX(90deg);
transition: transform var(--cd-nav-animation);
}
.cd-3d-nav--is-visible .cd-3d-nav__list {
transform: translateZ(0);
}
.cd-main {
transition: transform var(--cd-nav-animation);
}
.cd-main--is-translated {
transform: translateY(var(--cd-nav-height));
}
The .cd-3d-nav__marker
element has been used to create the marker for the selected navigation item (the <span>
is the bottom line, while its ::before
pseudo-element is the triangle).
In order to change the marker color, we defined the .cd-3d-nav__marker--col-n
classes (one for each navigation item). These classes change the color
and the background-color
of the .cd-3d-nav__marker
.
.cd-3d-nav__marker--col-1 { /* these are the colors of the marker - line + arrow */
color: var(--cd-color-2);
background-color: var(--cd-color-2);
}
.cd-3d-nav__marker--col-2 {
color: var(--cd-color-3);
background-color: var(--cd-color-3);
}
/* other classes here */
Events Handling
We used JavaScript to toggle the .cd-header--is-translated
/.cd-main--is-translated
/.cd-3d-nav--is-visible
classes when user clicks the navigation trigger.
Besides, when user selects one of the navigation list item, the left position of the span.cd-3d-nav__marker
is changed so that it is aligned with the selected element, and the proper .cd-3d-nav__marker--col-n
class is added (to change its background color).