'

Gmail Navigation in pure CSS3, how does it work?

We could call it a trend. If you take a look at the Gmail navigation, and then at the way buttons are styled on YouTube, you’ll start noticing similarities. When you over the navigation menu, the item you’re passing over slightly protrudes inviting you to perform the click. Once you comply, the item moves backward, simulating the pressing on a button.

Gmail Navigation in pure CSS3

It’s a cosy animation. Keeping the whole sum of animation discreet and elegant, we can use it among any kind of design.

I wondered if I could obtain a similar effect via pure CSS, and I’m quite happy with the result. In the demo page Gmail Navigation in pure CSS3 (and I would point without the use of Javascript) you can find three versions of the same menu.

The demo should work in any contemporary browser. If it does not work for you, please notify me, thanks!

Only HTML and CSS

I used a touch of HTML5 but that did not make any difference. The main purpose of the demo is to prove that a simple, clean markup can still express a nifty look with the help of a mere stylesheet. No jQuery or Javascript black mambo as been used here.

Pure CSS means that it’s lighter, probably faster. In my opinion the markup has to be as simplest as possible. I used the structure below.

<nav>
	<ul id="...">
		<li class="..."></li>
		<li class="... parent">
			<ul>
				<li class="..."></li>
				<li class="..."></li>
			</ul>
		</li>
	</ul>
</nav>

Each block has its own id (I mean each <ul>), while each item in the unordered list has its own class (each <li>). To target a parent of a drop down menu I had to add one more class, .parent. This shouldn’t be a big issue, since most of the CMSs add descriptive or functional classes anyway.

To be honest, I would like to avoid even the .parent class. Do you have any idea about how to target a <li> that has like descendant a <ul>? Please, let me know if you do.

Pseudo Elements

Pseudo Elements (:before and :after) have been used quite intensively to enhance graphic and user experience, and to reduce redundant markup.

Gmail Navigation in pure CSS3

Perhaps the most interesting solution has been applied to how submenus drop down. I wanted a drop down menu to appear only at the click on the relative button. Not just when we hover on it.

The CSS to display the drop down menus (simplified).

li ul {
	position: absolute;
	display: none;
	/* then styling */
}
li:active ul {
	display: block;
	opacity: 1;
}

To recall the drop down menu I’m using the :active pseudo class. Not :hover as usually we do. The user has to click on the button to access the submenu. Once he releases the mouse, this disappears. But at the same time we can keep the drop down menu visible if the user is hovering on it.

li:active ul,
li ul:hover { /* <- we added this line */
	display: block;
	opacity: 1;
}

But now we have an other problem. Since I don’t want the drop down menu to overlap with its parent, when the user clicks on the button, he’s not hovering on the submenu yet. He has to be super fast in clicking the button and then moving on the submenu, or the latter disappears as he releases the mouse. And here comes the solution.

I use a :before pseudo element of the child <ul>. How does it work?

An element that has display: none; is taken away from the normal flow of the page. So does not react on hovering. When we click on its parent (remember, li:active ul), then the property display switch to block). The element becomes visible and it’s already right below its parent (position: absolute;). Now, we need to keep in on screen when the user releases the mouse.

I thought a pseudo element could do the job. As soon as the submenu get back in game (display: block;) I sneak a pseudo element right under the mouse of the user (and on top of the button with a proper z-index). So, as soon as the user clicks on the button, he’s already hovering over (part of) the drop down menu. Isn’t cute?

Gmail Navigation in pure CSS3

In red the pseudo element :before, to keep the drop down visible once its parent got pressed. In green its brother :after which expands the area of sensibility of the <ul>. That’s a simple technique I decided to use for having a more tolerant behavior. The user could have difficulties in handling the device, and the pointer could slip few pixels outside the submenu borders while he’s just trying to reach the line he wish to click.

Below the lines that create the two pseudo elements.

li:hover ul:before,
li:hover ul:after {
	position: absolute;
	display: block;
	content: " ";
}

li:hover ul:before {
	top: -30px;
	left: 0;
	width: 75px;
	height: 30px;
}

li:hover ul:after {
	top: -5%;
	left: -5%;
	width: 110%;
	height: 110%;
	z-index: -1;
}

Tooltips

The three variants of the demo demonstrate various methods to render a Tooltip. In the first the browser does its honest job with its default behavior. When the user hovers on a button, a small yellow label usually shows up. Browsers traditionally use the Title attribute for this purpose.

<li class="ui-archive"><a href="#" title="Delete">Delete<span></span></a></li>

And here we see it in action.

Gmail Navigation in pure CSS3

In the other two, to avoid the default tooltip (which in some design looks cheap), I changed the attribute title in tooltip. So no yellow label any longer.

<li class="ui-archive"><a href="#" tooltip="Delete">Delete<span></span></a></li>

Once again, a pseudo element will take care of the tooltip.

a:after {
	content: attr(tooltip);
	display: block;
	position: absolute;
	/* then, style your tooltip */
}

Now you can style the tooltip at will. Don’t miss to set the property content and display: block; or you will not be able to give it precise (or relative) dimensions.

a:hover:after,
a:hover:after {
	visibility: visible;
	top: 44px;
}

Then you can style it to best fit your design. Below what I ended up with.

Gmail Navigation in pure CSS3

Gmail Navigation in pure CSS3

A note about Z-index

You’re probably confident with the concept of layers and z-index. It’s pretty straight forward, isn’t it?

Nevertheless, working with pseudo elements I discovered that there are some weirdos going on. Perhaps it’s due to how and when the browser creates the pseudo elements in the DOM. You will probably need to play a bit to find a good balance. Just as a tip, consider also assigning negative values. Sometimes it does the trick.

The Sprite… yes, it’s the Gmail one… no, they still don’t know I took it

I hope I’m not gonna break any royalties here, I wanted to use the same sprite you’re seeing in action on the Gmail Navigation. It’s exactly the same. In the file (png-24) the distance between the single icons isn’t smaller than the size of the button. I wanted to use (again) a pseudo element to position the icon at the middle of the button but I did not find any way to use background-position in combination with :before or :after.

So to visualize the icons I added a span just after the link.

<li class="ui-archive"><a href="#" title="Archive">Archive<span></span></a></li>

I’m still looking for a better solution. I would really like to find out how to use background-position with pseudo elements.

Vendors and compatibility

Not all browsers are made equal, and not all behave in the same way. Expect differences in the way different vendors render the page. Anyway, it should be accessible for the most. If you spot any issue, please provide me your feedback. Thanks!

Notes

Pay attention to few details, if you’re gonna use the code in your design.

The .parent class

A .parent class has to be added to have the little arrow pointing down when the button gives access to a submenu. I would like to get rid of the class, and find a way to select the button in more flexible way. Not a terrible problem, here, but better you know.

Direct descendants

The buttons have quite an intense styling applied on them. For differently styling the drop down menus (which are basically nested unordered lists), I opted for identifying the first level menu using direct descendant.

nav>ul>li {
	/* styling */
}

This way, nested list come unaffected, ‘cos they’re not direct descendants of the nav which contains all of them.

First and Last Child

To properly style the first and the last item in a group, I used the :first-child and :last-child pseudo classes.

nav>ul>li:first-child {
	margin-left: 0px;
	-webkit-border-radius: 2px 0 0 2px;
	-moz-border-radius: 2px 0 0 2px;
	-ms-border-radius: 2px 0 0 2px;
	-o-border-radius: 2px 0 0 2px;
	border-radius: 2px 0 0 2px;
}
nav>ul>li:last-child { 
	-webkit-border-radius: 0 2px 2px 0;
	-moz-border-radius: 0 2px 2px 0;
	-ms-border-radius: 0 2px 2px 0;
	-o-border-radius: 0 2px 2px 0;
	border-radius: 0 2px 2px 0;
}

But, again, this is quite simple. Eventually you will use the same approach if your design will require it. It’s much better than using the notorious classes .first and .last. Get rid of them!

The demo

To view (or download) the demo, visit the relative page Gmail Navigation in pure CSS3. Your feedback is very welcome, specially in order to make it better. Thanks!

One thought on “Gmail Navigation in pure CSS3, how does it work?

  1. Nice one, very neat. Thanks for sharing.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>