Responsive jQuery Tabs Tutorial

Responsive jQuery Tabs

View Demo Download

A web page with tabs is essential for displaying content in an informative and organized way. This simple responsive jQuery tab tutorial will help you create your own custom tabs using jQuery and CSS. The tabs will change to an accordion structure as you view them on mobile.

We’ll use CSS3 animations to animate content as one clicks each tab menu, but the animation degrades gracefully on old browsers. Remember to add your html5 shiv for those obsolete browsers and of course, the responsive meta tag.

Let’s fold up some sleeves and start coding!

HTML Markup

We’ll first introduce the tab menus on our html markup for each section.

<nav class="tabSelect">
    <ul>
        <li class="active"><a href="#">Section 1</a></li>
        <li><a href="#">Section 2</a></li>
        <li><a href="#">Section 3</a></li>
        <li><a href="#">Section 4</a></li>
    </ul>
</nav>

Next, we’ll add the tab sections, each with a class singleTab. We’ll then wrap them up in a div with class tabContent. Each singleTab will have an inside container div with class singleTabInner wrapping the tab’s content for each section.

<div class="tabContent">

    <article class="singleTab active">  
        <div class="singleTabInner">
            <header class="sectionTtl"><h2>Section 1</h2></header>
            <div class="contentText contentContainers">                	
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam imperdiet ut justo eget elementum. Suspendisse dolor quam, cursus quis urna et, faucibus ullamcorper augue. Quisque elit mauris, ultrices id metus vel, ornare pellentesque tortor. Curabitur aliquam porta libero et sodales. Cras vitae elementum libero. Fusce sollicitudin mi vitae elit scelerisque tincidunt. Vivamus mattis mi at ex auctor, at varius sem finibus. Ut quis rutrum lacus. Integer finibus ultrices leo, nec eleifend eros porttitor sed. Donec semper venenatis nunc, quis ultricies ligula dictum vel. Sed suscipit libero eu bibendum commodo. In gravida eros sed massa posuere ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed et congue quam.</p>
                
                <p>Fusce sollicitudin mi vitae elit scelerisque tincidunt. Vivamus mattis mi at ex auctor, at varius sem finibus. Ut quis rutrum lacus. Integer finibus ultrices leo, nec eleifend eros porttitor sed. Donec semper venenatis nunc, quis ultricies ligula dictum vel. Sed suscipit libero eu bibendum commodo. In gravida eros sed massa posuere ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed et congue quam.</p>
            </div>
            <div class="contentImg contentContainers">
                <img src="images/garden.jpg"/>                        
            </div>                    
        </div>
        <!--singleTabInner-->
    </article>
    <!--singleTab-->

    <article class="singleTab">
        <div class="singleTabInner">
            <header class="sectionTtl"><h2>Section 2</h2></header>
            <div class="contentText contentContainers">                	
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam imperdiet ut justo eget elementum. Suspendisse dolor quam, cursus quis urna et, faucibus ullamcorper augue. Quisque elit mauris, ultrices id metus vel, ornare pellentesque tortor. Curabitur aliquam porta libero et sodales. Cras vitae elementum libero. Fusce sollicitudin mi vitae elit scelerisque tincidunt. Vivamus mattis mi at ex auctor, at varius sem finibus. Ut quis rutrum lacus. Integer finibus ultrices leo, nec eleifend eros porttitor sed. Donec semper venenatis nunc, quis ultricies ligula dictum vel. Sed suscipit libero eu bibendum commodo. In gravida eros sed massa posuere ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed et congue quam.</p>
                
                 <p>Fusce sollicitudin mi vitae elit scelerisque tincidunt. Vivamus mattis mi at ex auctor, at varius sem finibus. Ut quis rutrum lacus. Integer finibus ultrices leo, nec eleifend eros porttitor sed. Donec semper venenatis nunc, quis ultricies ligula dictum vel. Sed suscipit libero eu bibendum commodo. In gravida eros sed massa posuere ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed et congue quam.</p>
            </div>
            <div class="contentImg contentContainers">
                <img src="images/road.jpg"/>                        
            </div>
        </div>
        <!--singleTabInner-->
    </article>
    <!--singleTab-->

    <article class="singleTab">
        <div class="singleTabInner">
            <header class="sectionTtl"><h2>Section 3</h2></header>
            <div class="contentText contentContainers">                	
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam imperdiet ut justo eget elementum. Suspendisse dolor quam, cursus quis urna et, faucibus ullamcorper augue. Quisque elit mauris, ultrices id metus vel, ornare pellentesque tortor. Curabitur aliquam porta libero et sodales. Cras vitae elementum libero. Fusce sollicitudin mi vitae elit scelerisque tincidunt. Vivamus mattis mi at ex auctor, at varius sem finibus. Ut quis rutrum lacus. Integer finibus ultrices leo, nec eleifend eros porttitor sed. Donec semper venenatis nunc, quis ultricies ligula dictum vel. Sed suscipit libero eu bibendum commodo. In gravida eros sed massa posuere ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed et congue quam.</p>
                
                 <p>Fusce sollicitudin mi vitae elit scelerisque tincidunt. Vivamus mattis mi at ex auctor, at varius sem finibus. Ut quis rutrum lacus. Integer finibus ultrices leo, nec eleifend eros porttitor sed. Donec semper venenatis nunc, quis ultricies ligula dictum vel. Sed suscipit libero eu bibendum commodo. In gravida eros sed massa posuere ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed et congue quam.</p>
            </div>
            <div class="contentImg contentContainers">
                <img src="images/mountain.jpg"/>                       
            </div>
        </div>
        <!--singleTabInner-->
    </article>
    <!--singleTab-->

    <article class="singleTab">
        <div class="singleTabInner">
            <header class="sectionTtl"><h2>Section 4</h2></header>
            <div class="contentText contentContainers">                	
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam imperdiet ut justo eget elementum. Suspendisse dolor quam, cursus quis urna et, faucibus ullamcorper augue. Quisque elit mauris, ultrices id metus vel, ornare pellentesque tortor. Curabitur aliquam porta libero et sodales. Cras vitae elementum libero. Fusce sollicitudin mi vitae elit scelerisque tincidunt. Vivamus mattis mi at ex auctor, at varius sem finibus. Ut quis rutrum lacus. Integer finibus ultrices leo, nec eleifend eros porttitor sed. Donec semper venenatis nunc, quis ultricies ligula dictum vel. Sed suscipit libero eu bibendum commodo. In gravida eros sed massa posuere ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed et congue quam.</p>
                
                 <p>Fusce sollicitudin mi vitae elit scelerisque tincidunt. Vivamus mattis mi at ex auctor, at varius sem finibus. Ut quis rutrum lacus. Integer finibus ultrices leo, nec eleifend eros porttitor sed. Donec semper venenatis nunc, quis ultricies ligula dictum vel. Sed suscipit libero eu bibendum commodo. In gravida eros sed massa posuere ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed et congue quam.</p>
            </div>
            <div class="contentImg contentContainers">
                <img src="images/coffee.jpg"/>                       
            </div>
        </div>
        <!--singleTabInner-->
    </article>
    <!--singleTab-->
    
</div>
<!--tabContent-->

CSS

We’ll proceed to styling the tab menus and the tab sections including their active states.

/** Tabs Navigation **/
.tabSelect {
    overflow: hidden;
}
.tabSelect li {
    float: left;
    width: 25%;
    position: relative;
}
.tabSelect li.active:after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: -2px;
    background: url(../images/arrow-active.png) no-repeat;
    width: 30px;
    height: 15px;
    margin-left: -15px;
}
.tabSelect li a {
    display: block;
    padding: 18px 0;
    font-size: 0.9375em;
    border-right: 1px solid #fff;
    color: #fff;
    text-align: center;
    text-transform: uppercase;
    font-family: 'Museo500Regular', Helvetica, Arial, sans-serif;
    background: #4CACBE;
    transition: all ease-in-out 0.3s;
    -webkit-transition: all ease-in-out 0.3s;
}
.tabSelect li.active a {
    background: #4CACBE !important;
}
.tabSelect li a:hover {
    background: #46BBD1;
}

On narrower screens, we’ll use different tab menus which will be added with jQuery and will only be displayed at that narrow size of screen.

.mobileTabLink {
    display: none;
    padding: 18px 0;
    font-size: 0.9375em;
    border-bottom: 1px solid #fff;
    color: #fff;
    text-align: center;
    text-transform: uppercase;
    font-family: 'Museo500Regular', Helvetica, Arial, sans-serif;
    background: #4CACBE;
    cursor: pointer
}

As each tab is selected, the tab content animates with subtle CSS3 transforms. We’ll add these cool effects on the tab titles using slideDown class and the tab content using the slideUp class. Remember to add the browser specific prefixes for the CSS3 animations included in the download.

/** Animations **/
.slideDown {
	animation-name: slideDown;
	animation-duration: 1s;
	animation-timing-function: ease;
	visibility: visible !important;
}

@keyframes slideDown {
	0% {
		transform: translateY(-20%);
		opacity:0;
	}

	100% {
		transform: translateY(0%);
		opacity:1;
	}
}
.slideUp{
	animation-name: slideUp;
	animation-duration: 1s;
	animation-timing-function: ease;
	visibility: visible !important;
}
@keyframes slideUp {
	0% {
		transform: translateY(5%);
		opacity:0;
	}

	100% {
		transform: translateY(0%);
		opacity:1;
	}
}

Now let’s get the action starting!

jQuery

Let’s start first by caching some variables that we are going to use on our jQuery code.

// Declaring Variables
var tabLinkContainer = $('.tabSelect'),
tabList = tabLinkContainer.find('li'),
tabLinks = tabLinkContainer.find('a'),
tabContent = $('.singleTab');

The real action begins to happen as we click each tab menu. I’ll go through each line in the clicking process so that it would be easy to understand.

We’ll need to capture the index position of the clicked tab parent (.tabSelect li) and store it in a variable.

// Click Tab Links
tabLinks.click(function(e){
	var parentIndex = $(this).parent().index();
});

Now, with CSS3 animations, it’s hard to re-run the animation when you click the same tab menu. Thanks to some workaround solution on how to restart CSS3 animation, we can by-pass this limitation.

Using the index we got from the clicked tab parent, we’ll get the tab content matching it using .eq(). Once jQuery has selected the corresponding tab content, it’ll look for the tab title for that particular tab content. We’ll then clone the tab title but remove the animation class in it slideUp and store it in a variable.

tabTitle = tabContent.eq(parentIndex).find('.sectionTtl'),
tabTitleNew = tabTitle.clone().removeClass('slideDown');

Once we’ve cloned the tab title, we’ll remove the original one from the DOM.

tabTitle.remove();

This cloning and removing of elements from the DOM helps restart CSS3 animation on our animated elements every time we click on the tab menus.
We’ll do the same process to the text and image of each tab.

// Cloning content and removing the original
contentContainers = tabContent.eq(parentIndex).find('.contentContainers'),
contentContainersNew = contentContainers.clone().removeClass('slideUp');
contentContainers.remove();

We’ll remove the active class from the last tab content that was on display, and the tab content whose index corresponds to the clicked tab menu parent is given an active class. Inside the container wrapping the tab’s content, .singleTabInner, we are going to prepend the cloned items.

tabContent.removeClass('active');
tabContent.eq(parentIndex).addClass('active').find('.singleTabInner').prepend(tabTitleNew,contentContainersNew);

The cloned items are then added the animating classes.

tabContent.find(tabTitleNew).addClass('slideDown');
tabContent.find(contentContainersNew).addClass('slideUp');

Of course we’ll remove the tab menu that was previously clicked  and add the active class to the current clicked tab menu.

tabList.removeClass('active');
$(this).parent().addClass('active');

We’ll remember also to disable the default anchor link action.

Mobile Bit…

The main reason for this tutorial was to show you how to make the tabs responsive. With jQuery, we’ll introduce a span with mobileTabLink class and store it in a variable. We’ll prepend the span in every tab content and they’ll act as our mobile tab menus.

var mobileTabLink = $('').prependTo('.singleTab');

After prepending the mobile tab menus, we’ll need to use the texts that were appearing on the tab menus on larger screens with these jQuery-added mobile tab menus. So, we’ll loop over each tab menus for larger screens that were had added in our html using .each(). As the jQuery loops, we’ll get the index and the text of each tab menu and store them in variables.

tabLinks.each(function(){
    var getIndex = $(this).parent().index(),
    getText = $(this).text();
});

We’ll then equate the index of each tab menu with that of its corresponding tab content where will find the mobile tab menus. The mobile tab menus are then given the text that was used on the tab menus on larger screens.

tabLinks.each(function(){
    var getIndex = $(this).parent().index(),
    getText = $(this).text();
    tabContent.eq(getIndex).find(mobileTabLink).text(getText);
});

For the final action on mobile, we’ll click or touch each mobile tab. As we do so, we’ll remove the active tab content and the also the active class on the tab menus on larger screens.

mobileTabLink.click(function(){
    tabContent.removeClass('active');
    tabList.removeClass('active');
});

We’ll then add an active class to the parent element of the mobile tab menu, which happens to be the tab content container, and also capture its index position and store it in a variable. The index position of the mobile tab menu parent will be used to get the corresponding tab menu index for the larger screens and have it to be active also.

mobileTabLink.click(function(){
    tabContent.removeClass('active');
    tabList.removeClass('active');
    var contentParentIndex = $(this).parent().addClass('active').index();
    tabList.eq(contentParentIndex).addClass('active');
});

You are probably wondering why we are still bothering with the active states of the tab menu for the larger screens when we click on the mobile tabs. This is because; some mobile phones will display the small screen version on portrait view and large screen version on landscape view. So we’ll need to show which menu tab and tab content is active when one switches between the two view modes.

And finally, we’ll add an active class to the first tab content and its corresponding tab menu to make it visible when the page loads. We can add the animating classes as the page loads to make it cooler!

$(window).load(function(){
	$('.sectionTtl').addClass('slideDown');
	$('.contentContainers').addClass('slideUp');
});

For our responsive CSS this is how the mobile version will be.

@media only screen and (max-width: 480px) {
    .tabSelect {
        display: none;
    }
    .singleTab {
        display: block !important;
    }
    .singleTabInner {
        display: none;
    }
    .singleTab.active .singleTabInner {
        display: block
    }
    .mobileTabLink {
        display: block;
    }
    .singleTab.active .mobileTabLink {
        background: #295861;
    }
    .contentContainers {
        width: 96%;
    }
    .contentImg {
        text-align: center;
        margin: 20px 0 0;
    }
    .contentImg img {
        width: auto;
        max-width: 100%;
        display: inline;
    }
}

That’s all folks! Hope you enjoy the responsive jquery tabs tutorial. Feel free to download the source files for your liking.

View Demo Download

Brian Kamau

Brian Kamau is a front-end web developer from Nairobi, Kenya with a passion for web and mobile. He's also a Christian Contemporary Music lover, a guitar enthusiast and the founder of Frontendry. View all posts by .

Your Online Shop on Shopify

Subscribe to our newsletter for the latest articles right in your inbox.