Skip to content

Instantly share code, notes, and snippets.

@gmilby
Created July 3, 2013 13:46
Show Gist options
  • Save gmilby/5917975 to your computer and use it in GitHub Desktop.
Save gmilby/5917975 to your computer and use it in GitHub Desktop.
Animated 3D Flipping Menu with CSS
The HTML
The HTML structure consists of a list with links, as you would expect from a navigation menu, however there are a few extra SPAN elements to aid the 3D effect:
<ul class="block-menu">
<li><a href="/" class="three-d">
Home
<span aria-hidden="true" class="three-d-box">
<span class="front">Home</span>
<span class="back">Home</span>
</span>
</a></li>
<li><a href="/demos" class="three-d">
Demos
<span aria-hidden="true" class="three-d-box">
<span class="front">Demos</span>
<span class="back">Demos</span>
</span>
</a></li>
<!-- more items here -->
</ul>
Beside the basic A element, a series of SPANs are used to represent the "front" and "back" faces of the 3D box during animation. Each should be given the same text as the A element.
The CSS
The animation centers around transitions and transforms. The actual A element wont move -- the parent SPAN element will. Each inner SPAN is initialized to its position and doesn't change. Each element animates upward and backward, using CSS transforms and CSS transitions, though one is on the rotation back while the other animates up into view.
/* basic menu styles */
.block-menu {
display: block;
background: #000;
}
.block-menu li {
display: inline-block;
}
.block-menu li a {
color: #fff;
display: block;
text-decoration: none;
font-family: 'Passion One', Arial, sans-serif;
font-smoothing: antialiased;
text-transform: uppercase;
overflow: visible;
line-height: 20px;
font-size: 24px;
padding: 15px 10px;
}
/* animation domination */
.three-d {
perspective: 200px;
transition: all .07s linear;
position: relative;
cursor: pointer;
}
/* complete the animation! */
.three-d:hover .three-d-box,
.three-d:focus .three-d-box {
transform: translateZ(-25px) rotateX(90deg);
}
.three-d-box {
transition: all .3s ease-out;
transform: translatez(-25px);
transform-style: preserve-3d;
pointer-events: none;
position: absolute;
top: 0;
left: 0;
display: block;
width: 100%;
height: 100%;
}
/*
put the "front" and "back" elements into place with CSS transforms,
specifically translation and translatez
*/
.front {
transform: rotatex(0deg) translatez(25px);
}
.back {
transform: rotatex(-90deg) translatez(25px);
color: #ffe7c4;
}
.front, .back {
display: block;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: black;
padding: 15px 10px;
color: white;
pointer-events: none;
box-sizing: border-box;
}
Some CSS properties may need to be vendor-prefixed.
If you want to a glimpse into which ways the front and back elements move (which I highly recommend you do), set one of them to display: none and hover over the element; you'll see what role each plays in the animation.
View Demo
The only downfall of this technique is the repeated menu label; it's easy to duplicate from a technical perspective, but screen readers may read said text three times, even with the aria-hidden="true" directive. The visual effect, however, is flawless in its style and silky smooth animation. No JavaScript, Flash, or canvas needed to create this effect -- just a few simple CSS directives. CSS animations...something to be very thankful for.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment