Tabbed panel interfaces are usually created using JavaScript, but this is unnecessary. This page describes how to style tabbed panels using CSS, as shown in the demonstration below, while keeping the semantic association between the tab labels and panel content.
Download examples
The archives below contain example files demonstrating the styling methods described on this page.
File | Size | Description |
---|---|---|
example.zip | 1,548 bytes | Zip archive |
example.7z | 1,465 bytes | 7-Zip archive |
The HTML
We begin with the following semantic HTML, which represents a panel as a section with a heading and content:
1 2 3 4 5 6 7 8 |
|
We then place the panels in a container and add radio buttons and labels:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
The radio buttons are used to indicate the currently selected panel.
If there are multiple sets of tabbed panels on a page, each must use a unique name for its radio buttons.
The first radio button has its checked
attribute set so that the first panel is shown by default.
The CSS styling
We start by hiding the radio buttons:
1 2 3 |
|
We then hide the content of any panel whose radio button is not checked:
1 2 3 |
|
We then display the tab labels in a row by floating them:
1 2 3 |
|
At this point the row of tab labels is interrupted by the content of the selected panel. We prevent this by floating the content to the right, with a negative left margin to prevent it affecting the layout and a top margin to position it below the labels:
1 2 3 4 5 |
|
Note that the required top margin depends on the styling of the tab labels. The value of 2.5 ems used here is based on a line-height of 1.5 combined with the tab styling described below.
We then style the container so that content following the tabbed panels appears below them:
1 2 3 4 |
|
Finally, we change the mouse pointer to indicate that tabs can be clicked, and prevent accidental selection of the tab text:
1 2 3 4 5 6 |
|
Making things look nice
The CSS above provides minimal styling for the panels. The following style rules will produce the appearance shown in the demonstration at the top of this page.
We start by displaying the selected panel content in a box with rounded corners:
1 2 3 4 5 6 7 8 |
|
We then display the labels as tabs with rounded corners:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
The use of padding and the overflow
property on the heading ensure that the tab shadow shows on the top, left, and right sides, but not the bottom.
We then indent the first tab so that it is not too close to the edge:
1 2 3 |
|
Finally, we stack the elements so that the selected tab appears above the panel content, which in turn appears above the other unselected tabs:
1 2 3 4 5 6 7 8 9 |
|
This causes the selected tab to overlap the panel content, covering up part of the border so that the tab appears joined to the panel content. The panel content also casts a shadow onto the unselected tabs.
Supporting older browsers
The code above works in any modern browser, but not Internet Explorer 8 or older.
By hiding the CSS rules with the negation pseudo-class — for example, by replacing each occurrence of .tabbed
with .tabbed:not(old)
— the semantic HTML ensures that the content will still be accessible in older browsers, with headings in the correct locations.