News

Create quick CSS3-only menus for mobile

Use CSS transitions to create animated menus on mobile to make sure you are getting the best possible speed boost

CSS3 Logo

The proliferation of designing your site for all screen sizes – also known as responsive design, mobile first, progressive enhancement, or a slew of other buzz phrases circling these ideas – has meant that particular attention is paid to the navigation. The navigation is an important part of any site because it allows the user to get around and discover the content.

Without a way to get around, your content won’t be viewed. In this tutorial we are going to build a custom mobile menu entirely from CSS, with no JavaScript, so we’ll use CSS3 transitions to enable animation within the menu. We’re going to tackle one of those menus where the content slides over to the left to reveal the menu behind. This was made popular by the Facebook mobile app, but is used everywhere now, even on Apple’s updated desktop software OS X.
You may be thinking, ‘Why don’t we just use a framework? There’s no point in building your own!’ While some frameworks include this kind of menu, often they can be quite bloated. By building your own you can customise more easily and leave out support for older browsers. After all, mobile browsers are all capable of running the latest CSS so no need to provide JavaScript fallbacks!

DOWNLOAD TUTORIAL FILES

Setting up the project

From the cover CD, copy the Start Folder onto your desktop and open the ‘index.html’  and ‘menu.css’ in a code editor such as Dreamweaver. Look at the page in a browser; it works fine at desktop resolution, but scaling down the browser you will notice that the design breaks. Add the code below to the top of the ‘menu.css’ file – this removes the toggle switch that appears above the menu.

001 .menu-toggle {display: none;} 

Detecting the screen

The toggle switch that we removed will actually be the switch that powers our CSS mobile menu and causes the menu to slide in and out. At the top of ‘menu.css’ add the code shown below. This is the code that will style the browser when displayed on small screens. The rest of our CSS will go before this closing bracket.

001 @media only screen and (max-width: 48em)    002 {
 003 /* All CSS will go here */
 004 } 

Stopping overflow

Our menu will appear in a column on the left-hand side of the screen, we’ll ensure that any overflow content on the x axis is hidden as the main content will slide over towards the right and we don’t want horizontal scrollbars visible. We add the code shown to combat this.

001 html, body { overflow-x: hidden; }

Position to the left

The next block of code positions our menu over to the left-hand side of the screen. We fix the position of this so that it doesn’t scroll with our page. After this, we position it in the top, left-hand corner of the browser so that the content will eventually be able to slide back and forth over the top of this.

001 nav {
 002 position: fixed;
 003 top: 0;
 004 left: 0;

Differentiating the menu

The menu is set to be the full height of the browser so that there is a consistent background colour down this left-hand side of the document. The colour we’ve chosen is a dark slate blue. We’ve set the background width to 250px but you could use a percentage, however this can end up being quite wide on tablets.

001 height: 100%;
 002 background: #3c4451;
 003 z-index: 0;
 004 width: 250px;
 005 }

Dodging bullets

We will remove the bullets that appear as default with unordered lists as this will help to get the menu to start looking more as it should. We also reset the margins and padding, we’ll set those in each of the links as we come to that part later. By having no padding or margins we will get a full background rollover effect behind the links.

001 nav ul {
 002 list-style: none;
 003 margin: 0;
 004 padding: 0;
 005 }

Content positioning

One of the problems is that the menu is over the content on the page. The way to correct this is to position the main content of the page absolutely. Notice that again we set this into the top left-hand corner of the document and make the <div> fill the width of the browser display.

001 #content {
 002  position: absolute;
 003 top: 0;
 004 left: 0;
 005 width: 100%;

CSS transitions

Finishing off the content <div> styling with the code shown will power the animation required. We’re stating that the transition should take two-tenths of a second and we are sticking with a linear transition. This is best for mobile as easing in and out can appear stuttered.

001 -webkit-transition: -webkit-transform 0.2s     linear;
 002 -moz-transition: -moz-transform 0.2s     linear;
 003 -o-transition: -o-transform 0.2s linear;
 004 -ms-transition: -ms-transform 0.2s linear;
 005 transition: transform 0.2s linear;
 006 }

Position the menu

Now we will turn our attention to the menu link that will open up the menu for us. We again position this absolutely and make it stretch the full width of the browser. Here we set it at a higher z index than other content on the page so that it remains on top.

001 .top-bar {
 002 position: absolute;
 003 width: 100%;
 004 z-index: 5;

Format the label

We can now style the menu bar more effectively. We position the label by adding some padding to the top/bottom and left/right of the <div> box. Make the text white so that it stands out against the background colour.

001.top-bar label {
 002 display: block;
 003 width: 100%;
 004 position: inherit;
 005 padding: 10px 20px;
 006 color: #fff;

Finish the label

We make the menu label a deep shade of slate blue – this makes the white text really stand out. The font size is increased as well so that it is more prominent on the page. Save the document and refresh the browser to see the changes now. The menu stands out but there is no functionality to make the content slide back and forth.

001 background: #2d333d;
 002 font-size: 1.6em;
 003 text-align: left;
 004 }

Change the words

So the menu bar is beginning to look good but we just want the word ‘Menu’ to be a little smaller while leaving the three lines looking the same. Using the code below we select the span around the word ‘Menu’. Here we scale it down slightly but this brings the text slightly up, so by positioning absolutely we can specify exactly where we want the text to appear.

001 .top-bar label span{
 002    font-size: 0.6em;
 003    display: block;
 004    position:absolute;
 005    top: 18px; left: 50px;
 006 }

Explaining the tilde

The next CSS might be unfamiliar to you. The tilde

(~) is the general sibling selector which means that the check box we hid in Step 1 is being checked on and off by its label in the content <div>. The tilde allows for the sibling to be disconnected from the original tag, which the content is if you check the HTML file.

001 #menu-toggle:checked ~ #content {
 002  -webkit-backface-visibility: hidden;
 003  -webkit-perspective: 1000;

Translate 3D

Using translate 3D as the transform for 2D movement ensures that the hardware GPU controls the animation – rather than the CPU which is what would happen if we were using jQuery. Here we are moving it over by 250px on the x axis. The translate 3D numbers refer to X, Y and Z in that order.

001  -webkit-transform: translate3d(250px,0,0);
 002  -moz-transform: translate3d(250px,0,0);
 003  -ms-transform: translate3d(250px,0,0);
 004  -o-transform: translate3d(250px,0,0);
 005  transform: translate3d(250px,0,0);
 006 }

Hardware-accelerated motion

Using the hardware to move the menu makes the animation smoother on mobile and small-screen devices – which is kind of the point of what we’re trying to achieve. In this step we simply move the content back 250px so the content slides back and covers the menu

001 #menu-toggle ~ #content {
 002  -webkit-transform: translate3d(0,0,0);
 003  -moz-transform: translate3d(0,0,0);
 004  -ms-transform: translate3d(0,0,0);
 005  -o-transform: translate3d(0,0,0);
 006  transform: translate3d(0,0,0);
 007 }

Attention to the menu

As the functionality of sliding back and forth is sorted, we need to turn our attention towards making the menu look better and function properly. Here we give the links a white colour, which will make them visible against the background. A slight padding gives them an indent of 25px from the left-hand edge of the browser.

001 nav li a {
 002  color: #fff;
 003  display: block;
 004  padding: 0 5px 0 25px;

Finish the links

As with most links, we remove the underline from under them by setting the decoration to none. We ensure that there is a good line height between each of the links and we add a one pixel dark slate blue line as a separator for each of the links. Save this and refresh your browser to see it looking much better now.

001   text-decoration: none;
 002   line-height: 2.6em;
 003   overflow: hidden;
 004   border-bottom: 1px solid #2d333d; }

Preparing for the rollover

Here we add a one pixel solid line to the top of each item on the menu. The line colour is the same colour as the background, which might seem a little odd, but when the rollover is completed you will see that this provides a little gap between the previous link. This is more useful for the Work link that has a nested menu list.

001 nav ul li 
 002 {
 003 border-top: 1px solid #3c4451;
 004 }

Rollover Effect

Now we add our hover rule for the link. Here we ensure that the background colour is strong so that it’s easily distinguishable from our background. We’re using the pink colour from the top of the homepage display. Save the page now and view this in the browser so that you can see the difference.

001 nav ul li:hover a
 002 {
 003  background: #FF6CFD;
 004 }

Indenting the nested menu

The menu is really taking shape, but one of the problems is that we have little distinction between the two levels of navigation. In order to help that, let’s increase the padding on the left-hand edge to 45px to give this submenu a difference in the way it looks. We’ve also changed the text colour here slightly as well.

001 nav ul ul li a 
 002 {
 003    color: #eee;
 004    padding: 0 5px 0 45px;
 005    margin: 0;
 006 }

Change the background

As the user hovers their mouse over the link we want to have a slightly different rollover effect to the pink that is already in place because of the Work element being selected. Here we add a dusty pink background, which provides suitable contrast to the text and the existing pink.

001 nav ul ul li a:hover             002
 003 {
 004    background: #90478A;
 005 }

Save and test

Save your CSS file and refresh your browser to see the menu in action. Ideally you want to see this on a mobile or tablet. We’ve tested on a variety of devices with good performance results. We’ve even had a dynamic animation in the canvas tag in the content area, and it’s still very good.

×