Advanced CSS Tabs

Since my first article on creating CSS Tabs (no images or JavaScript) there’s been a few questions on how to accomplish it with using click vs. hover method. Instead of rehashing over the same concepts, I’ll just review how to use the :target selector to create functional and progressive CSS Tabs based on my previous article. If you want to skip to the end, then you can just view the live demo.

Modified HTML

Since we are going to be using the target selector, we’ll need to add ID’s to the links, and selectors the the HREF attributes as well. This will allow us to select the tab via it's target, and it's next sibling from the same method. The new HTML for a link will be as follows:

<a id="tab1" href="#tab1">Scamper</a>

Modified CSS

With the HTML revised, now all we need to do is change the selectors from using :hover to :target.

.tabs a:target {
.tabs a:target:after {
.tabs a:target + section.tabs-content {

Why It’s Awesome

Of course using this native method versus a JavaScript solution will not only be lighter, but you get some built in awesomeness in that you can link directly to a tab when the page loads by specifying it’s identifier in the URL.

Example: Load CSS Tabs or Load with selected tab

So from here you can grab the code, use it, share it, graffiti all over it… enjoy!

View DemoDownload

83 Responses to Advanced CSS Tabs

  • [...] View Demo or Download. Update: I’ve updated this article to use CSS Target, check out the Advanced CSS Tabs.In the not so distant past I was getting excited at the prospect of creating scalable, resizable [...]
    viaCSS Tabs - No images or javascript
  • Awesome! Just learned something new in CSS :-) u made one more man happy.. One note though if the tabs are halfway the page, and you click a tab, the CSS target attribute pops the page to the top of the view. Feels kinda strange. In the demo you won't notice that, because it is already at the top of the page. Isn't anything to do about that in CSS I think, is it?
  • Hi Dex, you could argue this is a feature, not a bug, since it's just focusing the page at the location, but if you don't like you'd have to use a JavaScript solution to target the desired element.
    viaCaleb Ogden
  • Thank you very much)You're just a magician!!!)
  • Hi Caleb,
    Love the Advanced CSS Tabs article. I have one do you make the:

    auto adjust its height based on the content in this area. For example if I have content that is very long, how do I get the section to expand with it?

    Verizon Services
    viaWillis Frye
  • Hi Caleb,
    Sorry for the double post but looks like some of my comment did not make it.

    Love the Advanced CSS Tabs article. I have one question…how do you make the:

    section class="tabs-content"

    auto adjust its height based on the content in this area. For example if I have content that is very long, how do I get the section to expand with it?
    viaWillis Frye
  • Excellent! One question: I cannot work out how to load the webpage with one of the tabs (say Tab1 for argument's sake) pre-selected/displayed with out using JS to initiate a click event on the corresponding anchor? Is there a way using just HTML/CSS?
  • Hi John, you can just load the page with the hashtag already in the URL. So in my demo it'd be instead of just
    viaCaleb Ogden
  • Hi Willis, You'd have to set it up a bit differently. Instead of having it be it would have to be . Then you wouldn't position the content absolute, but rather just leave it static, and the height would auto adjust.
    viaCaleb Ogden
  • Hi Caleb,

    That's all well and good, but I'm looking for a way for the user (and search engines), who won't know, and shouldn't have to know, the 'home' (or any other) hash tag names within the code, to be able to simply enter the unadorned URL for the site ( rather than www/

    Reluctantly I looked at minimal JS methods for firing the 'home' tab anchor: however, simply executing (or alternatively in a element at the end of the , doesn't work; JS throws an error saying that element doesn't have that method.

    However, extending the HTMLAnchorElement with a click() method, (see thus ... = function() {
    var evt = this.ownerDocument.createEvent('MouseEvents');
    evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);

    ... and firing that in the does seem to work, at least in Google Chrome, which is where I've tested it thus far.

    But is there some other non-JS approach I could consider? E.g. Can I set the CSS attributes of the 'home' tab/content in some way (and if so, which would they be?)?
  • ... ah. My post has lost the mention of 'body' and 'body onload=' tags. Hopefully the places where gaps are are self-evident.
  • My question is the same as John's question.

    I would like to have tab1 loaded by default when the page loads without having to use the #tab1.

    Is there anyway to do this with just html/css?

  • same for me, i need tab1 already fired.
  • I was wondering how you would put a link into the content area without getting the circle in front of the link
  • Hi All,

    Regarding firing the first tab when the page loads: The short answer is, no, there isn't any easy way to fire without the hashtag in the URL using purely CSS. You maybe could find a work around using the weight of ID vs Classes in the same element, but it would be a convoluted solution.

    To fire tab one, a javascript solution is pretty straightforward. Using jQuery, here's an example of you it can be done.

    $().ready(function(){ $('#ID-OF-TAB-TO-LOAD').click(); });
  • Hi Caleb,

    The jQ code to trigger the 'default' tab doesn't seem to work. If I attached a handler to the anchor's click event, it gets executed. But, the tab content is not displayed.
  • Hi,

    Good idea with css tabs. But strange, tabs don't work in IE 8 when press 'View Demo'. Is ti cross-brower?
  • To have a specific page appear on load, I have the my content class as "tab1" and "tab", with the following css:
    .tab1{display: block;}
    .tab:target {display: block;}
    .tab:not(:target) {display: none;}
    :target {display: block;}
    :target +{display: none;}
    View the source code at
    Still building the site, but the main pages are almost complete.
    viaBrian Craig
  • Hi Caleb, I love your tabs! I was wondering the same thing as John about the tab content expanding when there is more text. Your reply seems to be truncated. Can you repeat how the css has to be changed? Thank you so much!
  • Sorry, it wasn't John's original comment, but Willis'.

  • Hi Brian,

    Are you using a different script now? I had look at your source code and it looks completely different... I was hoping to see how you did what you mention above. ;)
  • @Leo Make sure you have your hash tag in the href of the anchor
    @Peter For the sake of my health, I stay away from IE8. There very well may be issues with the demo, but the concept of using target to show / hide is cross-browser compliant.
    @Brian Thanks for sharing!

    @Phil the technique he's describing is just to have a sub-classed element (.tab1) set to display block on load.
  • Cool, thanks Caleb.
  • Thanks for sharing your code. This JavaScript will preselect tab1 on execution:

    window.location.hash = '#tab1';
  • This is splendid, being looking all over the web for this solution for a couple of days. Will take it for a ride and hopefully give some lovely feedback
  • Could I please get a push in the right direction on how to implement the #tab1 fix for displaying tab 1 content on page load many thanks.
  • hi
    How do I replace the icons do number 3 ؟
    #tab3:before { content: '3'; }
    icon is css3 with

    plz help me :(

Leave a comment

  • You may use these HTML tags and attributes
    <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>