This is a bit old - you may or may not notice the date on this post but it's over a year old. That doesn't mean it's not useful but we all know how fast things chance on the web so there's a chance that techniques and technologies described here could be a little dated.

CSS3 Hover Tabs without JavaScript

css tabs
With the new techniques in CSS3 and clever applications of existing CSS it is increasingly stepping on the toes of JavaScript. Which to be honest isn’t necessarily a bad thing.

I thought I’d try my hand at something so here is a basic CSS tabbed content section that changes on hover.

Click here to view the demo

So lets have a look

The HTML

[sourcecode language="HTML"]

Most Recent Posts

Most Popular Posts


[/sourcecode]

We have:

  • one containing div that has all the content in – #csstabs
  • two divs containing tab content and title – #tab1 #tab2
  • h3 tags for headings (can be changed to span or other heading tags)
  • tabcontent lists (these can be divs if you wanted)

The CSS

[sourcecode language="CSS"]

#csstabs{
position:relative;
width:300px;
height:290px;
}
#csstabs h3{
padding:5px;
height:30px;
text-align:center;
border-top:1px solid #000;
border-left:1px solid #000;
border-right:1px solid #000;
}
.tabcontent{
padding:10px 0 0 40px;
width:100%;
background:#fff;
border:1px solid #000;
}

[/sourcecode]

We give the CSS tabs a relative positioning so we can position things absolutely inside and then add a width and height to it. We then add to the h3 a height and borders on 3 sides and we give the tab content some padding and a background and border.

[sourcecode language="CSS"]

#tab1 .tabcontent{
z-index:2;
position:absolute;
left:0;
top:42px;
background:#fff;
height:230px;
}
#tab1 h3{
z-index:3;
width:150px;
position:absolute;
left:0;
top:0;
background:#fff;
}

#tab2 .tabcontent{
z-index:1;
position:absolute;
left:0;
top:40px;
height:230px;
}
#tab2 h3{
width:150px;
position:absolute;
left:180px;
top:0;
}

[/sourcecode]

We then assign values to the individual tabs.

.tabcontent gets a z-index with the higher number going to the tab that will be shown on the front in this case #tab1. They are then both given the same absolute positioning with the top value, placing the .tabcontent box just under the h3 tags so that on hover they cover a bit of the .tabcontent border.

They then get a background color and a height.

The h3 tags get a z-index of 3 to make sure they’re always on top, they get position absolutley to the top of the tabs with an appropriate left indent and are given a fixed width.

Then comes the hover bits

[sourcecode language="CSS"]

#csstabs:hover h3,
#csstabs:focus h3,
#csstabs:active h3{
background:none;
}

#tab1:hover h3,
#tab1:focus h3,
#tab1:active h3{
z-index:4;
background:#fff;
}
#tab1:hover .tabcontent,
#tab1:focus .tabcontent,
#tab1:active .tabcontent{
z-index:3;
background:#fff;
}

#tab2:hover h3,
#tab2:focus h3,
#tab2:active h3{
z-index:4;
background:#fff;
}
#tab2:hover .tabcontent,
#tab2:focus .tabcontent,
#tab2:active .tabcontent{
z-index:3;
background:#fff;
}

[/sourcecode]

Firstly when we hover over the containing div all h3 tags lose their background, that ensures the border line shows up underneath.
Then for tab1 and tab2 depending on which heading we’re hovering on the h3 get’s a z-index of 4 and a background color. The tabcontent gets the same but a z-index of 3. So both elements are brought to the front with the h3 further forward.
Because the h3 overlaps the tabcontent box by 1px you can move seemlessly from the h3 element into the tabcontent without losing the focus, it also means that the current header will cover the border of the tabcontent box making it look connected.

CSS3
But wait, what’s that? You have a webkit browser? Well how about some CSS3 tricks. It’s not much but a little fade between the tabs? Oh ok then.

So first things first add opacity:0 to any .tabcontent boxes that aren’t shown intially.
[sourcecode language="CSS"]
#tab2 .tabcontent{
z-index:1;
position:absolute;
left:0;
top:42px;
height:230px;
opacity:0;
}
[/sourcecode]

Then under your #csstabs:hover h3 declaration add this.
[sourcecode language="CSS"]
#csstabs:hover .tabcontent,
#tabs:focus .tabcontent,
#tabs:active .tabcontent{
opacity:0;
-webkit-transition : opacity .75s ease-in;
}
[/sourcecode]

That will fade out the .tabcontent areas in 0.75 seconds easing into the animation, pretty self explanitory really!

Finally for the .tabcontent hover classes we need to add a fade in.

[sourcecode language="CSS"]
#tab1:hover .tabcontent,
#tab1:focus .tabcontent,
#tab1:active .tabcontent{
z-index:3;
background:#fff;
opacity:1;
-webkit-transition : opacity 2s ease-in;
}

#tab2:hover .tabcontent,
#tab2:focus .tabcontent,
#tab2:active .tabcontent{
z-index:3;
background:#fff;
opacity:1;
-webkit-transition : opacity 2s ease-in;
}
[/sourcecode]
So that will fade in the .tabcontent that is being hovered over in 2 seconds again easing in.

So there you go you’re now using CSS3, exciting isn’t it!

Drawbacks
Whilst at first glance it all works nicely there are two main drawbacks of the technique. It requires a fixed height and width, although giving the tabcontent box an overflow:scroll can help if you can live with the scrollbars. Which is great for plenty of situations but not necessarily for dynamically generated content.

The other is that so far I haven’t got it working for tabbing through the page so there are issues regarding the accessibility of the links.

Want to do something with CSS? HTML? JavaScript? Want to see more tutorials? Let me know what you’d like to see via the contact page – I’m happy to take on a challenge!