I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my other blogs

Massive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

CSS Tab Navigation

css / navigation

Estimated reading time: 3 minutes

An array of folder tabs can work as a navigational metaphor for some sites. Creation of the tabs is relatively straightforward: the basic markup would be the navigational list I’ve used many times before:

<nav id="tabbed-navigation">
<a href="#">Home</a>
<a href="#">About Us</a>
<a href="#" id="forefront">Products</a>
<a href="#">Contact</a>
<a href="#">Your Privacy</a>

We’ll set the links side by side with a slight curve on the top corners using border-radius, and supply a linear-gradient and box-shadow, as each tab will eventually overlap slightly:

nav#tab-navigation a {
font-family: Avenir, Helvetica, sans-serif;
display: inline-block;
text-transform: uppercase;
text-decoration: none;
color: #fff;
padding: 0.8rem 2.6rem 2rem 2.6rem;
border: 1px solid #777;
border-radius: 5px 5px 0 0;
background: linear-gradient(#dfc891, #776c51);
box-shadow: 0 0 15px rgba(0,0,0,0.5);
letter-spacing: .15rem;
text-shadow: 0 1px 0 #000;
font-size: 1.4rem;
transition: 0.2s transform linear;

I’ve added a tiny bit of text-shadow to separate the link text from the background; the transition is in place for the UI hover effect we will add in a moment.

I’ve set 2rem in padding to the bottom of the links to make them extra high; I'll hide the excess of this by setting overflow: hidden and a set height on the containing <nav> element:

nav#tab-navigation {
padding-top: 2rem; padding-left: 2rem;
overflow: hidden; height: 4rem;
width: max-content;
margin: 0 auto;

I’ve also used the woefully little-known width: max-width to set the <nav> element’s width from the collective dimensions of its child elements.

Next, we want to overlap the tabs. That’s easy: we’ll just apply a negative margin-left value to all of them except the first element:

nav#tab-navigation a:nth-child(n+1) {
margin-left: -1.2rem;

(Remember this selection pattern, as we’ll return to it later).

The overlapping tabs will stack in the order the links appear in the code. To indicate which page the user is on, we will push one tab to the foreground and upwards by using the forefront id. forefront will have position: relative (since we want to “nudge” the link without disturbing the others) and a z-index to visually push it to the foreground:

a#forefront {
position: relative;
top: -0.2rem;
z-index: 2;

Next, we want to animate the hover effect on the tabs. We’ll do so with a simple transform. I’ll also add an a:focus selector for touchscreen devices that are unable to detect :hover:

nav#tab-navigation a:hover, nav#tab-navigation a:focus { transform: translateY(-.4rem);  }

You’ll find one small issue: the first link will “pop” above the others during its transition, due to the assumptions of CSS animation. We can fix this by ensuring that the other links are always “higher” in the stack, returning to the selection pattern we used earlier:

nav#tab-navigation a:nth-child(n+1) {
margin-left: -1.2rem;
position: relative;
z-index: 2;

To make the navigation continue to work at smaller window sizes, I'll reduce some dimensions at an appropriate breakpoint, stacking them on top of each other at the low end:

@media screen and (max-width: 800px) {
nav#tab-navigation { height: 3rem; }
nav#tab-navigation a {
font-size: 1.1rem;
padding: 0.8rem 1.4rem 2rem;
@media screen and (max-width: 500px) {
nav#tab-navigation { height: auto; }
nav#tab-navigation a { display: block; margin-top: -1rem; }

The only remaining issue is one of efficiency: in order to change which tab is actively in the foreground to indicate which page we are on, we would need to move the id onto the appropriate tab on each page. While this is certainty achievable, it is time-consuming, especially if we add more pages. It also means that we could not use the navigation as a server-side include.

In past articles I have shown how to get around this issue by using PHP to create “self-aware pages”; as a different solution, I also show the same idea implemented in a more elegant fashion with JavaScript. Play with the code for the CSS Tabs navigation on CodePen

comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.