An array of folder tabs can work as a navigational metaphor for some sites. Creation of the tabs is relatively straightforward: the basic HTML 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>
</ul>
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-content
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.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/aeJKA