Grow your CSS skills. Land your dream job.

Smooth tab to content transition in CSS

  • # October 26, 2008 at 8:17 am

    I’ve created a tabbed interface using jQuery for my WP theme but I’m having a little problem styling it in CSS the way I imagined it.

    Currently it looks like this:
    [img]http://img183.imageshack.us/img183/9713/tabln3.png[/img]

    What I’m trying to achieve is obviously delete/hide the border between the current tab and the content. It’s a part of content’s border so it’s impossible to just remove a part of it from CSS, so I was thinking maybe positioning the tabs absolute and then pushing them one pixel down where they’re selected? I’m sure there IS some method to achieve this effect, I just can’t figure out it. Help would be appreciated :)

    Here’s the code for this part:

    Code:

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

    This is the list of the most recent comments!

    Code:
    #recent li {
    background: #fff url(‘../images/latest-bg.jpg’) top left repeat-x;
    border: 1px solid #ccc;
    border-bottom: none;
    float: left;
    margin: 0 5px 0 0;
    }

    #recent li a, a:visited, a:hover {
    text-decoration: none;
    color: #444;
    padding: 3px 5px 3px;
    display: block;
    }

    #recent li a:hover {
    font-weight: bold;
    }

    #recent li a.current-tab {
    font-weight: bold;
    background: #fff url(‘../images/tab-bg.jpg’) top left repeat-x;
    }

    #recent-posts, #popular-posts, #recent-comments {
    border: 1px solid #ccc;
    width: 278px;
    padding: 15px 10px 10px;
    background: #fff;
    }

    # October 26, 2008 at 11:50 am

    That method would work. So would inscreasing the bottom padding on that tab. In either case you would want to push the sides of the tab down to where they touch the content border and then remove the bottom border from the tab.

    The hard part will be in programatically identifying which tab to deal with, unless you want to hard code a different version for each page. Fortunately, Chris wrote an article about how to do just that. I don’t have the link handy but I’ll look. It involves using a bit of php to set the id on the body tag to the basename of the file. Here’s my version:

    Change your <body> tag to <body id="<?php echo basename($_SERVER, ‘.php’); ?>">

    Then add some CSS similar to:

    BODY#page1 UL.menu LI { border-bottom: none; padding-bottom: XXpx; }
    BODY#page2 UL.menu LI { border-bottom: none; padding-bottom: XXpx; }

    BODY#pagen UL.menu LI { border-bottom: none; padding-bottom: XXpx; }

    where page1, page2, etc are the names of the pages.

    That will probably need some tweaking. I just woke up and probably missed something but that’s the general idea. Hope that helps.

    # October 26, 2008 at 2:22 pm

    Well like I said, I’m using jQuery to make the tabs work, the function adds a class (current-tab) to the tab/li element that is currently showed. So adding a bit of CSS to that specific class wouldn’t be a problem. The problem is figuring out WHAT to add to CSS to make it work :)

    I’ve tried setting the div containing the tabs and content divs to position: relative and then setting tab’s position to absolute with a high z-index and a bit more of bottom padding. It doesn’t work tho, the only thing that did was removing side borders of that tab.

    What I did:

    Code:
    #sidebar div#recent {
    width: 298px;
    float: left;
    margin-bottom: 20px;
    position: relative;
    }
    #recent li a.current-tab {
    font-weight: bold;
    background: #fff url(‘../images/tab-bg.jpg’) top left repeat-x;
    position: absolute;
    padding-bottom: 2px;
    border-bottom: none;
    z-index: 50;
    }

    Result:
    [img]http://img58.imageshack.us/img58/9485/picture1tq4.png[/img]

    Hmm…

    # October 26, 2008 at 6:30 pm

    This will do exactly what you describe without the need for any jQuery. Works as is as a demo. In practice, put everything above the <body> tag in a header file and include it on every page.

    Code:
    < ?php /* Menu Tab Example */ ?>

    < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">




    If your script does anything else you should be able to modify this to work with it. Enjoy.

# October 27, 2008 at 7:21 am

Your method works great Mikes, however it assumes that every time a tab is clicked, the page is reloaded => <body> get a new id. Well, in my example it doesn’t reload, when the tab is clicked, it shows some content in the div below it. That’s what I used jQuery for ;)

In fact, lets forget about the behaviour at all and focus on the presentation. The first tab has a class of "current-tab", just so it can have different background etc. I re-wrote the markup to match yours as much as possible but I still can’t force that "current-tab" to work properly :(

Code:
#recent {
width: 298px;
float: left;
margin-bottom: 20px;
}

#recent ul#tabs {
display: block;
}

#recent ul#tabs li a {
background: #fff url(‘../images/latest-bg.jpg’) top left repeat-x;
border: 1px solid #ccc;
float: left;
padding: 3px;
margin: 0 5px 0 0;
display: inline;
}

#recent ul#tabs li a, a:visited, a:hover {
text-decoration: none;
color: #444;
}

#recent ul#tabs li a:hover {
font-weight: bold;
}

#recent ul#tabs li a.current-tab {
font-weight: bold;
background: #fff url(‘../images/tab-bg.jpg’) top left repeat-x;
border-bottom: none;
padding-bottom: 4px;
}

#recent-posts {
width: 278px;
float: left;
margin-bottom: 20px;
border: 1px solid #ccc;
padding: 15px 10px 10px;
background: #fff;
}

# October 27, 2008 at 10:56 am

I played with absolute positioning a bit and almost got what I wanted :)
http://zencreations.boo.pl/current-tab.mov

The current-tab is positioned absolute inside the div#recent and moved down one pixel on click, making it cover that part of containers border. I didn’t absolute positioned the other tabs cause I want it to be as fluid as possible and setting fixed values for left positioning isn’t an option I think. Any idea how to make the "normal" tabs act normally, i.e. stay in their positions while still being able to move the "current" one down?

This is what I changed in the code since the last post:

Code:
div#recent {
width: 298px;
float: left;
margin-bottom: 20px;
position: relative;
z-index: 0;
}
Code:
#recent ul#tabs li a.current-tab {
font-weight: bold;
background: #fff url(‘../images/tab-bg.jpg’) top left repeat-x;
padding-bottom: 3px;
position: absolute; top: 1px;
z-index: 1;
}
Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.

*May or may not contain any actual "CSS" or "Tricks".