written on:27 Jan, 2011 by Alen Grakalic

Styling Full Width Tabs with CSS3

Delicious StumbleUpon Reddit Subscribe

In this article I will demonstrate how to create full width "browser-like" tabs using pure CSS3 and some HTML5 markup. This article includes whole lot of new CSS properties such as box and text shadows, border radius and CSS gradients. That means a lot of vendor prefixes in the code :).

CSS3 tabs

Of course, not all browsers support these properties, so we need to make sure that everything degrades nicely. I mean as nice as a it could be, right?

It degrades from this (Safari)

Tabs in Safari

to this (IE8)

Tabs in IE8

Markup

First let's take a look at the markup. In this example I am using HTML5 elements.
Head of the document looks like this:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Tabbed Layout</title>
<link rel="stylesheet" href="css/screen.css" type="text/css" media="screen" />
<!--[if IE]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]-->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript" src="js/tabbed.layout.js"></script>
</head>

We are using John Resig's HTML5 Shiv to make sure we can properly render HTML5 elements in all browsers, and I am including a Easy Framework's tab script just to add behavior to the tabs.

Next in the markup structure is the header...

<header>
<h1>Some cool goes title</h1>
</header>

...and then we go to the nav element. This element contains actual clickable tabs:

<nav> 
    <ul>
        <li><a href="#tab1">Tab 1</a></li>
        <li><a href="#tab2">Tab 2</a></li>
        <li><a href="#tab3">Tab 3</a></li>
        <li><a href="#tab4">Tab 4</a></li> 
    </ul>
</nav>

We link the tabs to the section elements further down in the markup structure:

<section class="tab" id="tab1">
<p>Section number 1</p>
</section>

<section class="tab" id="tab2">
<p>Section number 2</p>
</section>

<section class="tab" id="tab3">
<p>Section number 3</p>
</section>

<section class="tab" id="tab4">
<p>Section number 4</p>
</section>

As far as the necessary markup goes, this is it. Pretty simple!

CSS3 Magic

First let's edit the header. Header has fixed height and we added a subtle CSS gradient to it, from darker to lighter:

header{
    height:32px;
    overflow:hidden;
    background:#e1e1e1;
    background:-webkit-gradient(linear, left top, left bottom, from(#d1d1d1), to(#e1e1e1));
    background:-moz-linear-gradient(top,  #d1d1d1,  #e1e1e1);
    padding:0 5px;
    }

Nav element has fixed height as well, list items inside are floated to the left and have the same width. We are also adding CSS gradients along with bottom border radius and box shadow. (vendor prefixes galore)

nav li{
    list-style:none;
    float:left;
    height:24px;
    line-height:24px;
    -moz-box-shadow:0 0 3px #888;
    -webkit-box-shadow:0 0 3px #888;
    box-shadow:0 0 3px #888;
    -webkit-border-bottom-right-radius:3px;
    -webkit-border-bottom-left-radius:3px;
    -moz-border-radius-bottomright:3px;
    -moz-border-radius-bottomleft:3px;
    border-bottom-right-radius:3px;
    border-bottom-left-radius:3px;
    margin:0 2px;
    width:200px;
    overflow:hidden;
    position:relative;
    background:#ccc;
    background:-webkit-gradient(linear, left top, left bottom, from(#ccc), to(#aaa));
    background:-moz-linear-gradient(top,  #ccc,  #aaa);
    }

Selected tab should blend into header so the colors must match. "Ending" color of the header gradient must be "starting" color of the selected tab. Also make sure that you define matching regular background colors for browser that don't support CSS gradients.

nav li.selected{
  background:#e1e1e1;
  background:-webkit-gradient(linear, left top, left bottom, from(#e1e1e1), to(#d1d1d1));
  background:-moz-linear-gradient(top,  #e1e1e1,  #d1d1d1);
  }

Styling the anchor's inner shadow

Now here's a little trick. I guess you are familiar with box-shadow property and how it works. What we can define is horizontal offset, vertical offset blur and a color. Another cool option that allows us to have inner shadows is the inset attribute. Here is our problem... on non selected tabs, we need to have only top shadow, no shadows from the side. That is not doable with the usual settings

What we'll do is:

  • add inner shadow to anchor element with vertical offset only
  • make a nested anchor element wider than the parent LI element
  • position anchor absolutely inside the LI element
  • set overflow to hidden on LI element

That way we will simply hide the side inner shadow and have only top shadow visible. This is small detail, but without it the entire tab would not look natural (as if the header drops a shadow on it).

Take a look at the graphic to (hopefully :) ) understand it better.

Hiding side shadows

Here's the CSS for the anchor element:

nav li a, nav li a:visited, nav li a:hover{
  list-style:none;
  display:block;
  position:absolute;
  top:0;
  left:-2px;
  height:24px;
  line-height:24px;
  width:204px; 
  text-align:center;
  color:#333; 
  font-size:11px;
  text-shadow:#e8e8e8 0 1px 0;
  -moz-box-shadow:inset 0 1px 1px #888;
  -webkit-box-shadow:inset 0 1px 1px #888;
  box-shadow:inset 0 1px 1px #888;
  } 

Selected anchor doesn't have an inner shadow:

nav li.selected a{
  -moz-box-shadow:none;
  -webkit-box-shadow:none;
  box-shadow:none; 
  } 

JavaScript

Last but not least, I added a simple tab script, because without it, tabs... well... wouldn't make that much sense. This script is taken directly from my Easy front-end framework code.

tabs = function(options) {
    
    var defaults = {  
        selector: '.tabs',
        selectedClass: 'selected'
    };  
    
    if(typeof options == 'string') defaults.selector = options;
    var options = $.extend(defaults, options); 

    return $(options.selector).each(function(){
                                
        var obj = this;	
        var targets = Array();

        function show(i){
            $.each(targets,function(index,value){
                $(value).hide();
            })
            $(targets[i]).fadeIn('fast');
            $(obj).children().removeClass(options.selectedClass);
            selected = $(obj).children().get(i);
            $(selected).addClass(options.selectedClass);
        };

        $('a',this).each(function(i){	
            targets.push($(this).attr('href'));
            $(this).click(function(e){
                e.preventDefault();
                show(i);
            });
        });
        
        show(0);

    });			
}
// initialize the function
tabs('nav ul');

Note that we are passing a selector as a parameter to the function. This selector must be a unordered (or ordered) list of the tab navigation.

Take a look at the demo or Download files

That is it! In my next article I will take this one step further and create a full screen tabbed layout so stay tuned!

About the author

cssglobe's image

Designer, developer and a passionate standardista. Long time web professional with huge experience in all types of front-end work. Founder of Css Globe and creator of Easy front-end framework.
To get in touch, visit Alen's personal page, follow Alen on Twitter or become a Facebook friend.

Enjoyed the article?

Then don't miss our next one! Subscribe to our RSS feed or share it with your friends.

Delicious StumbleUpon Reddit Subscribe

Read more! Here are our most recent articles:

View All Articles

Comments

  1. Red 28 Jan, 2011

    Very nice result, thanks for sharing!
  2. Joost 29 Jan, 2011

    Looks very sexy. Nice way of 'clipping' the box-shadow.
    Since the tabs have a fixed width, it would be very trivial to have an image fall-back for the more css3-challenged browsers out there.
  3. Web Design Company 29 Jan, 2011

    CSS3 is modularized and consists of several separate recommendations. If we want to follow the development of CSS3, this is the place to start to learn..Really fantastic post...
  4. Petr Lev 30 Jan, 2011

    Nice article, thanks
  5. Izdelava internetne strani 30 Jan, 2011

    Awsome tutorial. Just what i was looking for my next website navigation! Thanks.
  6. Laura 31 Jan, 2011

    Great blog. I love your articles so much. Keep on!
    Laura
  7. jack 1 Feb, 2011

    Hi its great i enjoy reading your post
  8. Joseph Taylor 1 Feb, 2011

    Very nice demonstration! I'm salivating over the possible uses!
  9. Robert Visser 1 Feb, 2011

    One aspect I'd like to see implemented is to pass the #tab1, #tab2, #tab3, #tab4, etc to the URL. In all of our A/B testing enabling an ability to bookmark individual tabs garners better UX responses -- at least in instances where tabs were used for primary page navigation as opposed to loading content into a small window.

    In the full page version, I'd like to see the CSS take advantage of orientation media queries.

    Thanks for the post.
  10. Chris F.A. Johnson 2 Feb, 2011

    A good article, apart from using fixed heights (the demo doesn't work for me; the text is cut off at the bottom).
  11. csabi 3 Feb, 2011

    Hi! I just love your tutorial! Congratulations!
    I`we just opened a tutorials indexing website and I would like to ask you to submit your tutorials, it will bring you some extra traffic
    Please give a chance for my website: http://www.tutorialswindow.com

    Thanks!
  12. stevewckrt 4 Feb, 2011

    Very nice demonstration!
    http://www.bugsketch.com
    Watch live football games streaming on your computers.Never miss another football game again.
    Our instant access site allows you to Watch Live Football Online On Your PC minutes after subscribing. We provide access to all of the latest football streams and live soccer feeds.
  13. san fransisco 8 Feb, 2011

    It's helping me in my work.Thank you so much.

Sorry, further comments are disabled for this post.

CSS Globe is a web design magazine brought to you by Alen Grakalic and kept fresh with member contributed news and exlusive articles.

CSSG Ads

Useful Links

Friends