How to Create a CSS3-Only Tab Control Using the :target Selector

Share this article

Do we need another tab control? Probably not, but this example demonstrates the power of the CSS3 :target selector. We’re going to build an attractive animated tab control using HTML5 and CSS3. You won’t need JavaScript or images and it works in IE9, Chrome, Firefox, Safari and Opera.

Essential Features

You’ll find many CSS3-only tab controls throughout the web. However, many have issues such as:
  • not displaying any tab content if you link to the page without a hash selector, i.e. you link to mypage.html rather than mypage.html#tab1.
  • not highlighting the active tab.
This solution overcomes those problems — view the demonstration page…

What about IE6, 7 and 8?

Were you expecting modern CSS3 effects to work in a browser released in 2001? IE7 and 8 will show the first tab only. IE6 shows the last tab, although it’d be easy to set it to the first. You therefore have two options:
  1. Don’t offer legacy browser support. IE users won’t know they’re missing anything so, if the content’s not vital to your page, you could choose to ignore them.
  2. But that’s not nice. The quickest solution is to add the selectivizr shim. Alternatively, resort to a better progressively enhanced solution and forget about this flaky CSS3 nonsense.

The HTML

Here’s our basic HTML5 code. Tab content is contained within a section. The tab itself is the first child and defined as an h2 element with an inner link to the outer section:

<article class="tabs">

	<section id="tab1">
		<h2><a href="#tab1">Tab 1</a></h2>
		<p>This content appears on tab 1.</p>
	</section>
	
	<section id="tab2">
		<h2><a href="#tab2">Tab 2</a></h2>
		<p>This content appears on tab 2.</p>
	</section>
	
	<section id="tab3">
		<h2><a href="#tab3">Tab 3</a></h2>
		<p>This content appears on tab 3.</p>
	</section>

</article>
This is different to HTML tab code you’ve seen before. The majority of controls define the tabs as a ul list followed by each content section. Although it’s possible to use similar mark-up, it makes tab highlighting far more difficult because the tab itself can’t be styled using :target. The best solution I found was to add a pseudo-element to the section which was colored accordingly and positioned under the tab text. That quickly became a convoluted mess.

The CSS

First, we’ll style the article container. It’s sized and has its position set to relative so we can position the sections:

article.tabs
{
	position: relative;
	display: block;
	width: 40em;
	height: 15em;
	margin: 2em auto;
}
This is followed by the sections. They’re all absolutely positioned 1.8em from the top to allow room for the tabs. The box-shadow is fairly light because each section is stacked on top of one another:

article.tabs section
{
	position: absolute;
	display: block;
	top: 1.8em;
	left: 0;
	height: 12em;
	padding: 10px 20px;
	background-color: #ddd;
	border-radius: 5px;
	box-shadow: 0 3px 3px rgba(0,0,0,0.1);
	z-index: 0;
}
Since the last tab will be shown on top, we’ll switch it to the first tab by setting a higher z-index:

article.tabs section:first-child
{
	z-index: 1;
}
We can now style the tabs. These are colored in their ‘off’ state and positioned higher than our sections. The left positions of the second and third tabs are adjusted to ensure they’re not overlaying each other.

article.tabs section h2
{
	position: absolute;
	font-size: 1em;
	font-weight: normal;
	width: 120px;
	height: 1.8em;
	top: -1.8em;
	left: 10px;
	padding: 0;
	margin: 0;
	color: #999;
	background-color: #ddd;
	border-radius: 5px 5px 0 0;
}

article.tabs section:nth-child(2) h2
{
	left: 132px;
}

article.tabs section:nth-child(3) h2
{
	left: 254px;
}

article.tabs section h2 a
{
	display: block;
	width: 100%;
	line-height: 1.8em;
	text-align: center;
	text-decoration: none;
	color: inherit;
	outline: 0 none;
}
All our tabs and sections are now defined and tab 1 is shown by default even when none of the sections are targeted in the URL. We can now change the color, background-color and z-index of the active section using the :target selector:

article.tabs section:target,
article.tabs section:target h2
{
	color: #333;
	background-color: #fff;
	z-index: 2;
}
As a bonus, let’s add a transition effect when the targeted tab is changed:

article.tabs section,
article.tabs section h2
{
	-webkit-transition: all 500ms ease;
	-moz-transition: all 500ms ease;
	-ms-transition: all 500ms ease;
	-o-transition: all 500ms ease;
	transition: all 500ms ease;
}
View the demonstration page… Unlike many JavaScript solutions, our CSS3 widget retains the full history of tab views so the browser back and next buttons operate correctly. It’s also possible to link directly to a tab from anywhere in the page — as illustrated by the ‘NEXT’ links. It’s not perfect; when you initially link to the page, the first tab is active but shown in the ‘off’ state. It’s difficult to overcome that issue … unless you can think of a solution? The easiest fix would simply make the ‘on’ and ‘off’ state differences a little more subtle. It doesn’t end there, either. Because we’re using CSS, we can transform the tab control into other widgets without altering the HTML mark-up. Stay tuned to SitePoint… If you enjoyed reading this post, you’ll love Learnable; the place to learn fresh skills and techniques from the masters. Members get instant access to all of SitePoint’s ebooks and interactive online courses, like Learn CSS3. Comments on this article are closed. Have a question about CSS3? Why not ask it on our forums?

Frequently Asked Questions (FAQs) about CSS3 Tabs Using Target Selector

How can I create a basic tab structure using HTML and CSS3?

Creating a basic tab structure using HTML and CSS3 involves a few steps. First, you need to define the HTML structure. This includes creating a div element for each tab and assigning them unique IDs. Then, you need to create an unordered list (ul) that will serve as the navigation menu for the tabs. Each list item (li) will contain a link (a) that targets the corresponding div ID.

Next, you need to style the tabs using CSS3. This involves setting the display property of the div elements to none, which hides them by default. Then, you can use the :target selector to display the div that corresponds to the clicked link. You can also add styles to the active tab to differentiate it from the others.

What is the purpose of the :target selector in CSS3?

The :target selector in CSS3 is used to select and style an element that has an ID matching the current URL fragment. In the context of creating tabs, it allows you to display the content of the clicked tab and hide the others. When a link is clicked, the URL fragment changes to match the ID of the targeted div, which triggers the :target selector.

How can I add transitions to the tab switching?

You can add transitions to the tab switching by using the transition property in CSS3. This property allows you to specify the duration and easing function of the transition. For example, you can use the following code to add a 0.5-second transition to the opacity and height of the tab content:

.tab-content {
transition: opacity 0.5s, height 0.5s;
}

How can I create nested tabs?

Creating nested tabs involves a similar process to creating regular tabs, but with an additional level of div elements and links. Each parent tab contains a set of child tabs, each with their own unique ID and corresponding link. The CSS3 :target selector is used to display the content of the clicked child tab within the active parent tab.

How can I make the tabs responsive?

Making the tabs responsive involves using media queries in CSS3. These allow you to apply different styles depending on the width of the viewport. For example, you can stack the tabs vertically on smaller screens and display them horizontally on larger screens.

How can I add icons to the tabs?

You can add icons to the tabs by using the ::before or ::after pseudo-elements in CSS3. These allow you to insert content before or after the text of the link. You can use an icon font like Font Awesome or an image as the content.

How can I add a default active tab?

You can add a default active tab by using the :target selector in combination with the :not() and :first-child pseudo-classes. This allows you to display the first tab by default when no other tab is targeted.

How can I add a hover effect to the tabs?

You can add a hover effect to the tabs by using the :hover pseudo-class in CSS3. This allows you to change the style of the link when the mouse pointer is over it.

How can I add a dropdown menu to a tab?

You can add a dropdown menu to a tab by creating a nested unordered list within the list item of the tab. You can then use CSS3 to hide the dropdown menu by default and display it when the tab is hovered over.

How can I add a scrollbar to the tab content?

You can add a scrollbar to the tab content by using the overflow property in CSS3. This allows you to add a scrollbar when the content exceeds the height of the tab.

Craig BucklerCraig Buckler
View Author

Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.

CSSHTML5 Dev CenterHTML5 Tutorials & Articles
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week