Zoom navigation

Menu

To demo the interaction, press the menu button.

- 2 min read

Most small screen navigation patterns fall into two major categories, patterns that show you all of the navigation items from a glance of the screen and those that don't. There are some technical constraints as to why the execution of these patterns have stayed mostly the same, you might notice that you rarely/never see fixed footer locked navigation on websites like you might in native applications, that's mainly because of a problem Android browsers have with layering links.

Navigation patterns which show you everything are useful for simple quick tasks and for simple websites - they run into problems when navigation reaches a certain level of complexity and screen real estate becomes an issue.

Patterns which disclose navigation through an interaction are more useful for complex navigation systems, as far as the interaction is concerned it's switching modes between reading/consuming content to navigating.

The most popular form of discosure pattern is the 'off canvas,' or 'side-drawer' pattern, which has become a staple for applications like Facebook, Youtube and Twitter on their small screen variants.

The experiment

This experiment combines the timing sequences from the cascade experiment with an off-canvas navigation pattern, but instead of using animation-delay, this uses transition delay. The whole effect is a combination of 3 different transitions.

Three transitions

The first part is the container of the entire page - this container needs to scale, and move to the side when the button is active. One thing to keep in mind for this is that you'll want the body background to be different to the container to distinguish the mode switch between content and navigation.

			
	/*
		In this case, the parent frame needs a few things for this to work well
	*/
	.d-frame {

		/* A clearly different background */
		background:url('/experiments/img/zoom-navigation_bg.jpg') no-repeat #111;

 		/* Relative positioning for the navigation items */
		position:relative;

	}

	/*
		Initial state:
		We only need to apply the transition to listen for the transform
		Setting the transform origin will allow us to make it feel like it is
		zooming out
	*/

	.d-content {

		transition:transform 0.5s ease-in-out;
		transform-origin:bottom right;
	}


	/*
		Toggled state:
		We scale the content 70%,
		then move it to the right 50% of its size
		and down 10% of its size.
	*/

	.d-frame.is-toggled .d-content {

    	transform:scale(0.7) translateX(50%) translateY(10%) translateZ(0);

	}


			
		

The second part is the off canvas coming in and translating from the side to it's normal position. This is not so dissimilar to any off canvas pattern.

			


	.d-navigation-inner {


		/*
			You want the navigation to be positioned absolutely,
			this will mean it won't push the entire content of the page down
		*/
		position:absolute;

		/* Then we set it to be -100% to the left of its position. */

  		transform:translateX(-100%) translateZ(0);

  		/* And listen for a transform change */
  		transition:transform 0.4s ease-in-out;
  		width:100%;


	}

	/*
		Toggled state:
		set it's translateX to where it was before it was translated

	*/
	.d-frame.is-toggled .d-navigation-inner {

    	 transform:translateX(0) translateZ(0);

    }


			
		

The third and final part is revealing each list item and moving them slightly down.

			

	/*
		Initial state:
		each link is positioned slightly downward
		and made invisible
	*/

	.d-navigation-inner li a {

		opacity:0;
		transform:translateY(0.75em) translateZ(0);
  		transition:opacity 0.4s ease, transform 0.5s ease-in-out;
	}

	/*
		Toggled state:
		each link is revealed,
		then moved to their intended location,
		this fires the transition above

	*/

	.d-frame.is-toggled .d-navigation-inner li a {

 		 opacity:1;
 		 transform:translateY(0) translateZ(0);

	}

	/*
		Then we give each list item a different delay,
		so they come on individually rather than as a block
	*/
	.d-frame.is-toggled .d-navigation-inner li:nth-of-type(1) a {

        /*
        	In this case, each item is delayed
        	by an increment of 0.1s,
        	so the second item would be 0.2s and so on.
        */

        transition-delay: 0.1s;

     }

			
		

The text flicker bug

While chrome is a very forgiving browser when it comes to animation, browsers like Safari 7.1 and Firefox 32 still do the old text flicker bug. This bug usually occurs when animating type - when the animation or transition completes the type then flickers into place, sometimes the kerning changes a little.

It's a really jarring bug, fortunately it's easy enough to fix with the Null Hack (adding translateZ(0) to your transitions to force it onto a 3d layer and become GPU assisted). The new 'will-change' property will hopefully fix this up but for now, null hacks and forced 3d layers are necessary.

Unfortunately, the browsers which need will-change the most, are also the browsers which as I write this, don't currently support will-change.

A little caution for using the null hack, pushing everything to the GPU will cause low-powered devices to become sluggish, so always test and use sparingly. This is no magic bullet.

			

	/*
		Hacks make me feel dirty, but sometimes you have to.
		The good news is this fixes the problem in Safari and Firefox
	*/

	.d-navigation-inner {

		/*
			Adding translateZ(0) to the navigation element
			is enough for Safari and Firefox
		*/

		transform:translateX(0) translateZ(0);
	}