
INSPIRATION: runbetter.newtonrunning.com
Setting the stage
The main menu for the site starts with a background image featuring a Gradient Overlay and a Lens Flare effect, applied with Photoshop. Gradient Overlay allows you to dither the gradient, reducing gradient banding and produce a much smoother gradient upon image compression. Then, using custom code, we generate 13 <div> elements with a white background and low opacity, randomly positioned and rotated in 3D space to complete the stage. This results in a different pattern each time a user revisits the site.
001 .plane {
002 position: absolute;
003 top: 50%;
004 left: 50%;
005 width: 6000px;
006 height: 3000px;
007 margin: -1500px 0 0 -3000px;
008 background-color: #fff;
009 opacity: 0.08;
010 }
011 for (var i = 0; i <= number_of_planes; i++) {
012 $nav_bg.append(‘<div class=”plane”
style=”’ + NPL_ENV.util.transform +
‘: translate3d(‘ + _.random(-2000,
2000) + ‘px, ‘ + _.random(-1500,
1500) + ‘px, ‘ + _.random(-4500,
-5000) + ‘px) rotateX(‘ +
_.random(-60, 60) + ‘deg) rotateY(‘
+ _.random(-60, 60) + ‘deg)
rotateZ(‘ + _.random(-60, 60) +
‘deg);”></div>’);
013 }
Construct the scene
The scene lays in front of the background in Z space (z-index). To enhance the feeling that the user is in a 3D world, we generate 100 particles that are randomly positioned, rotated and coloured in 3D space. When a user flies through the world, the particles are what make it feel 3D. Next, we place the menu items inside this scene to complete the effect.
001 .particle {
002 position: absolute;
003 top: 50%;
004 left: 50%;
005 width: 0px;
006 height: 0px;
007 margin: -12px 0 0 -17px;
008 border-left: 24px solid transparent;
009 border-right: 24px solid transparent;
010 border-bottom: 24px solid #fff;
011 }
012
013 for (var i = 0; i <= number_of_
particles; i++) {
014 $particles.append(‘<div class=”particle” style=”opacity:
‘ + Math.random() + ‘; ‘ + NPL_ENV.util.transform + ‘: translate3d(‘
+ _.random(-2000, 2000) + ‘px, ‘
+ _.random(-1500, 1500) + ‘px, ‘
+ _.random(-4000, -10) + ‘px)
rotateX(‘ + _.random(-60, 60)
+ ‘deg) rotateY(‘ + _.random(-60,
60) + ‘deg) rotateZ(‘ + _.random
(-60, 60) + ‘deg);”></div>’);
015 }
Active menu
In order to move into the active menu state, we added a CSS transition on the 3D transform of each button. Then we simply zero out the transforms aside from the one that rotates the item 45 degrees. This makes each item animate from its place in our 3D scene to the foreground so the user can interact with it. The borders and image fades into the background on hover are also achieved with a simple CSS transition.
001 .zone {
002 ...
003 transition: all 800ms cubic-bezier(0.645, 0.045, 0.355, 1.000);
004 }
Fly to section
The final stage is to fly to a section after a user has clicked a menu item. To do this, we write the 3D transform back on to the menu items. The transition makes them animate back into 3D space. Next, we transform the entire scene again with a CSS transition by applying values exactly opposite (and in the opposite order) of the selected menu item and zoom the selected menu item. The transitions meet to give the user the feeling that they are flying through the scene while the selected item is filling up the screen.
001 .zone {
002 ...
003 transition: all 800ms cubic-bezier(0.645, 0.045, 0.355, 1.000);
004 }
005 .zone#zone-4.fly {
006 transform: rotateX(10deg) rotateY(10deg) rotateZ(10deg) translateZ(-4500px);
007 }
008 #scene {
009 ...
010 transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) translateZ(0px);
011 transition: transform 800ms cubic-bezier(0.645, 0.045, 0.355, 1.000);
012 }
013 #scene.zone-4 {
014 transform: translateZ(4500px) rotateZ(-10deg) rotateY(-10deg) rotateX(-10deg);
015 }
016