How to Create Responsive Pure CSS Tabs

In this tutorial I’m going to show you how to create Responsive Pure CSS Tabs. We’ll be using Font-Awesome to add icons to the tab labels, so we can hide the text label and leave only the icons on smaller screen size.

[tutorial_details]

Content tabs are almost everywhere nowadays, you can see them in website sidebars, login/register pages, portfolio/personal web site and so on. They are used to display multiple blocks of content that you can switch between without reloading the page. For example, on a authentication page, you’d have two or three tabs depends. One for the login form, one for registration and sometimes one for password recovery.

To get started, we’ll need to download and include font-awesome into our project. You can download it here.

The HTML Markup

For the HTML, we create a div container with the class “tabs”, this will hold our tabular content. Then we add our radio buttons and beneath each radio button we add a label. The radio buttons will get the name “tabs” and each of them will have a Unique ID of “tab1” “tab2” and so on. As for the label, we have an icon and some text. The text is inside some <span> tags so we can hide them on devices with smaller screen sizes.

Below the radio buttons and their labels, we add the content containers. Each box has a class of “tab-content” and an ID of “tab-content1” “tab-content2” and so on. We use these IDs to match the correct labels and display the correct content attached to the label. As you can see we used the ID of “tab1”  on the first radio button, and we use “tab-content1” on the first content. This way we can easily display and hide them.

<div class="tabs">
    <!-- Radio button and lable for #tab-content1 -->
    <input type="radio" name="tabs" id="tab1" checked >
    <label for="tab1">
        <i class="fa fa-html5"></i><span>HTML5</span>
    </label>
    <!-- Radio button and lable for #tab-content2 -->
    <input type="radio" name="tabs" id="tab2">
    <label for="tab2">
        <i class="fa fa-css3"></i><span>CSS3</span>
    </label>
    <!-- Radio button and lable for #tab-content3 -->
    <input type="radio" name="tabs" id="tab3">
    <label for="tab3">
        <i class="fa fa-code"></i><span>jQuery</span>
    </label>
    <div id="tab-content1" class="tab-content">
        <h3><!-- Tab title here --></h3>
        <p><!-- Tab content here --></p>
    </div> <!-- #tab-content1 -->
    <div id="tab-content2" class="tab-content">
        <h3><!-- Tab title here --></h3>
        <p><!-- Tab content here --></p>
    </div> <!-- #tab-content2 -->
    <div id="tab-content3" class="tab-content">
        <h3><!-- Tab title here --></h3>
        <p><!-- Tab content here --></p>
    </div> <!-- #tab-content3 -->
</div>

The CSS

As styling goes, we’re going to apply some simple but visually appealing style to our content tabs. We align the labels side by side, giving them a 33.333% width, since we have 3 tabs. If you have more, you can change this value. For example if you have four tabs, you can use 25% and so on. For the content area, apply a small css animation to make it pop when the content of the tab is changed, giving the new content some more attention. Also, we hide the radio buttons by default, since we use the labels as the “clickable” area.

.tabs {
    max-width: 90%;
    float: none;
    list-style: none;
    padding: 0;
    margin: 75px auto;
    border-bottom: 4px solid #ccc;
}
.tabs:after {
    content: '';
    display: table;
    clear: both;
}
.tabs input[type=radio] {
    display:none;
}
.tabs label {
    display: block;
    float: left;
    width: 33.3333%;
    color: #ccc;
    font-size: 30px;
    font-weight: normal;
    text-decoration: none;
    text-align: center;
    line-height: 2;
    cursor: pointer;
    box-shadow: inset 0 4px #ccc;
    border-bottom: 4px solid #ccc;
    -webkit-transition: all 0.5s; /* Safari 3.1 to 6.0 */
    transition: all 0.5s;
}
.tabs label span {
    display: none;
}
.tabs label i {
    padding: 5px;
    margin-right: 0;
}
.tabs label:hover {
    color: #3498db;
    box-shadow: inset 0 4px #3498db;
    border-bottom: 4px solid #3498db;
}
.tab-content {
    display: none;
    width: 100%;
    float: left;
    padding: 15px;
    box-sizing: border-box;
    background-color:#ffffff;
}

The Animation

As for the animation, we simple create a @keyframe that has 3 frames. 0%, 50% and 100%. At 0% the size of the content is 0.9, at 50% it’s 1.1 and at 100% it’s 100%. With this, we give the content a kind of “bounce” effect by making the content smaller, then bigger and then back to it’s original size.

.tab-content * {
    -webkit-animation: scale 0.7s ease-in-out;
    -moz-animation: scale 0.7s ease-in-out;
    animation: scale 0.7s ease-in-out;
}
@keyframes scale {
  0% {
    transform: scale(0.9);
    opacity: 0;
    }
  50% {
    transform: scale(1.01);
    opacity: 0.5;
    }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

The Mechanics

To make our tabs function we need to add a little bit more CSS. First we give the active label a different style by using the :checked + label. This will change the style of the label that is attached to the checkbox that is checked. If… that makes any sense.

Then, we check which checkbox is checked, and display the content with that is attached to it using the IDs we specified above. ( #tab1:checked ~ #tab-content1 ) This will display the content box with the ID of “tab-content1” if the checkbox with the ID of “tab1” is checked.

.tabs [id^="tab"]:checked + label {
    background: #FFF;
    box-shadow: inset 0 4px #3498db;
    border-bottom: 4px solid #3498db;
    color: #3498db;
}
#tab1:checked ~ #tab-content1,
#tab2:checked ~ #tab-content2,
#tab3:checked ~ #tab-content3 {
    display: block;
}

Making it Responsive

If you payed close attention to the CSS styles above, you noticed that we hide the <span> inside the labels by default. This is because we made a mobile first approach. So to make it them appear on larger screens, we need to use a @media query. Besides making the text on the labels appear, we also adjust the margins and paddings on the icons, and set a max-width for the .tabs container.

@media (min-width: 768px) {
    .tabs i {
        padding: 5px;
        margin-right: 10px;
    }
    .tabs label span {
        display: inline-block;
    }
    .tabs {
    max-width: 750px;
    margin: 50px auto;
    }
}

And that’s it. You can play around with the styles and settings as you like. If you add more tabs, don’t forget to follow the pattern of #tab1, #tab2 etc and #tab-content1, #tab-content2. Also update the CSS styles by adding these ids to the #tab1:checked ~ #tab-content1 code block.

I hope you enjoyed this tutorial on how to create responsive pure css tabs. Let me know what you think about this approach and if you know any other way of doing this, feel free to post it below! Same goes for any questions and/or suggestions.