views:

98

answers:

5

Hi, I'm coding a tab system for my website that must be entirely CSS/HTML/JS (without using any images). Problem is, I keep hacking the code until when I'm finished its just a mess. I don't know whether to use positioning, or float the tabs or what. Basically one of the big problems is that after I take away the bottom-border CSS of the selected tab, I need to move it down 1px so it seamlessly blends with the sorting headers - I don't know whether to use margin: -1px or position: relative/absolute etc. I'd love some advice on a good way to code a tab system like this, so that it can be reused across the website!

alt text

+2  A: 

I would use divs nested inside a list.

<ul>
<li>Tab1
    <div> Content for Tab1</div>  
</li>
<li>Tab2
    <div> Content for Tab2</div>  
</li>
<li>Tab3
    <div> Content for Tab3</div>  
</li>
</ul>

Then with css style ul li div to not show. I would use jQuery to show the child divs upon click of the parent li.

EDIT: Thanks to the comment... Note the li's would have to be styled inline so they do not break line after every one. Also set the li list-style to none.

Capt Otis
I like this solution, and I've used it myself. But you should note that it requires `display: inline`.
Lord Torgamus
Persoanlly I beleive that it can get a little messy getting the inside divs into position. Also this will probably degrade in non-JS browsers not quite as well as the solution I describe below.
thomasfedb
Yeah thomas your solution degrades better.
Capt Otis
+1  A: 

In my opinion I would write it like this:

<div class="tabContainer">
    <ul class="tabList">
        <li><a href="#item1">Item 1</a></li>
        <li><a href="#item2">Item 2</a></li>
        <li><a href="#item3">Item 3</a></li>
    </ul>

    <em class="tabMessage">This is the message on the right.</em>

    <div class="tabInnerContainer">
        <div id="item1">
            bla
        </div>
        <div id="item2">
            bla
        </div>
        <div id="item3">
            bla
        </div>
    </div>
</div>

This way will allow you to make it function al least to some extent without Javascipt, degrading nicely in browsers with JS turned off. Some of the classes could be removed if using CSS3 sleectors.

thomasfedb
I also recomend you use jQuery or similar if you can for the js.
thomasfedb
Thanks for the comment, how would you move the selected tab down so that it overlapped 1px with the bottom of the InnerContainer so they blended into looking like one piece? Absolute positioning, negative margins?
Walker
I would give that li a negative -1px bottom margin, or a top margin of 1px. And I'd keep everything relative.
Capt Otis
+1  A: 

I assume the problem is to make the tab and the bar below it seem like one piece without using too much code.

What I have done before is to make the two elements I want to join overlap slightly (or not at all) and then put a third element (in the same color as both other elements) where the overlap is. This acts as a kind of patch.

Like this:

I. without patch

     _________________ 
    |                 |
    |    tab          |
  __|_________________|________________________________
 |                                                     |
 |       menu bar                                      |
 |_____________________________________________________|

II. with patch

     _________________ 
    |    tab          |
    |- - - - - - - - -|
 ___|    patch        |_______________________________
|    - - - - - - - - -                                |
|        menu bar                                     |
|_____________________________________________________|

You will only need to use z-indexes to make this work properly. The patch may extend over the tab div it is contained in by using position: absolute and an adequately high value for top.

Update: demonstration

http://jsfiddle.net/7GJaW/

FK82
This seems overly messy and non-semantic, if it can be achived without excess elements, why wouldn't you?
thomasfedb
For one, your example does not cover rounded borders. My solution addresses this nicely. Also it is neither messy nor non-semantic (what does that mean anyway?). I posted a link to a demo on jsfiddle.net
FK82
A: 
Louis Stephens
Thats exactly what I use, except a div would work better in this example. Plus its easy to manipulate nested elements through javascript/jquery.
Capt Otis
+1  A: 

Here's an example with CSS that makes it work:

HTML:

<body>
    <div class="tabs">
        <ul>
            <li><a href="#item1">Item 1</a></li>
            <li class="active"><a href="#item2">Item 2</a></li>
            <li><a href="#item3">Item 3</a></li>
        </ul>
        <div class="tabInner">
            <div id="item1">
                bla1
            </div>
            <div id="item2">
                bla2
            </div>
            <div id="item3">
                bla3
            </div>
        </div>
    </div>
</body>

CSS:

.tabs ul {
    list-style: none;
}

.tabs ul li {
    float: left;
    background: #eee;
    border: 1px #aaa solid;
    border-bottom: none;
    margin-right: 10px;
    padding: 5px;
}

.tabs ul li.active {
    margin-bottom: -1px;
    padding-bottom: 6px;
}

.tabInner {
    clear: both;
    border: 1px solid #aaa;
    height: 200px;
    overflow: hidden;
    background: #eee;
}

.tabInner div {
    height: 200px;
    padding: 10px;

}

It even works without JS (to some degree). You'll still need some JS to move the 'active' class arround and also if you want fancy transitions.

See it in action here: http://jsfiddle.net/V8CK4/

thomasfedb
Thanks, worked really well! I'll show you what I ended up with when I commit it.
Walker
Good to know I could help!
thomasfedb