3D Rotating Navigation

3D Rotating Navigation

A 3D rotating navigation, powered by CSS transformations.

Nucleo logo Sponsored by Nucleo, a powerful icon manager for web designers

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.

The icons included have been created by the talented Vlad Cristea and can be downloaded for free on GraphicBurger.

Creating the structure

We created a <header> element to wrap the logo and the trigger for the rotating navigation (.cd-3d-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-marker has been appended to the <nav> to create the marker for the selected item in the navigation.

<header class="cd-header">
   <a href="#0" class="cd-logo"><img src="img/cd-logo.svg" alt="Logo"></a>
   <a href="#0" class="cd-3d-nav-trigger">Menu<span></span></a>

   <!-- all your content here -->

<nav class="cd-3d-nav-container">
   <ul class="cd-3d-nav">
      <li class="cd-selected">
         <a href="#0">Dashboard</a>

      <!-- other list items here -->

   <span class="cd-marker color-1"></span><!-- marker for the selected navigation item -->

Adding Style

To realise our animation, we used CSS3 Transformations applied to the <header>, <main> and <navigation> elements.
Here is a quick preview to show you the animation process (.gif created in After Effects).


By default, the navigation (.cd-3d-nav-container) is hidden right above the viewport (translateY(-100%) and visibility(hidden)), while the unordered list (.cd-3d-nav) is rotated (rotateX(90deg) and transform-origin: bottom center). When user clicks the trigger element, the class .nav-is-visible is added to the <main>, <header> and <nav> elements which are translated of a quantity equal to the navigation height while the .cd-3d-nav is rotated back (rotateX(0)). CSS3 Transitions have been used to achieve a smooth animation.

.cd-header {
  transition: transform 0.5s;
.cd-header.nav-is-visible {
  transform: translateY(80px);

.cd-3d-nav-container {
  /* this is the 3D navigation container */
  position: fixed;
  top: 0;
  left: 0;
  visibility: hidden;
  /* enable a 3D-space for children elements */
  perspective: 1000px;
  transform: translateY(-100%);
  transition: transform 0.5s 0s, visibility 0s 0.5s; 
.cd-3d-nav-container.nav-is-visible {
  visibility: visible;
  transform: translateY(0);
  transition: transform 0.5s 0s, visibility 0.5s 0s; 
.cd-3d-nav {
  /* this is the 3D rotating navigation */
  transform-origin: center bottom;
  transform: rotateX(90deg);
  transition: transform 0.5s; 
main {
  transition: transform 0.5s;
main.nav-is-visible {
  transform: translateY(80px); 

The .cd-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 .color-n classes (one for each navigation item). These classes change the color property of the .cd-marker. Since we set background-color : currentColor, changing the color updates the background-color too.
Beside, we set border-bottom-color: inherit for the .cd-marker::before element, which is also updated changing its parent color property.

.cd-marker {
  background-color: currentColor;
.cd-marker::before {
  /* triangle at the bottom of nav selected item */
  height: 0;
  width: 0;
  border: 10px solid transparent;
  border-bottom-color: inherit; 

/* these are the colors of the markers - line + arrow */
.color-1 {
  color: #9a57bd; 

.color-2 {
  color: #c96aa4; 

/* other classes here */

Update: due to a bug on Chrome, we had to use the .color-n class to change the background-color (rather than using the currentColor value).

Events Handling

We used jQuery to add/remove the .nav-is-visible class when user clicks the navigation trigger.
Besides, when user selects one of the navigation list item, the left position of the span.cd-marker is changed so that it is aligned with the selected element, and the proper .color-n class is added (to change its background color).

💌 Join our newsletter

Get our monthly recap with the latest CodyHouse news