Wednesday, December 4, 2013

How to make a Tabbed Panel using CSS without Javascript

    Tabbed Panels are not a new thing, they have been around on your desktop since the first graphic interface. The web is here, but we don't do things like pepperidge farm remembers. A long time ago netscape came up with this client side scripting language, we call javascript, ECMAScript for picky. It has proven very useful for all sort of things. And more recently thankfully or not with the explosion of libraries like jQuery, you probably see Tabbed Panels everyday on the web too.

But Today I was fiddling around and I found something that I though it was very cool and I want to share with you guys that it is possible to make a Tabbed Panel with pure CSS and markup, without Javascript.

Don't get me wrong, I love javascript and I write javascript everyday, but is very cool to see that it is possible to do this kind of things without it.

DEMO

JSFIDDLE http://jsfiddle.net/Victornpb/h2nb6/

Tab 1

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.

Tab 2

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin iaculis diam eget leo dapibus suscipit. Integer vulputate lacinia libero, nec interdum diam consectetur non. Quisque elementum augue lectus, id euismod risus bibendum quis. Integer nec turpis facilisis, vestibulum mi vel, mattis nisi. Integer et sapien odio. Pellentesque enim ipsum, dictum vel malesuada non, elementum sed augue. Curabitur quis lectus libero. Proin vel elementum quam. Nam ipsum ligula, condimentum nec ante vitae, sollicitudin auctor elit. Morbi et elementum lectus. Aenean vulputate lobortis nunc.

Tab 3

Quisque orci metus, elementum et purus vitae, fringilla dictum orci. Sed tincidunt, lectus vitae bibendum vehicula, turpis nisi pharetra ante, et posuere diam sem eget metus. Curabitur id felis non odio aliquam dignissim. Fusce volutpat vulputate enim quis pellentesque. In ut nunc eleifend, rutrum velit non, sollicitudin lectus. Praesent fringilla ipsum lectus, condimentum varius elit accumsan nec. Curabitur hendrerit, orci pretium pulvinar lobortis, nunc metus ultricies elit, vel sodales urna erat et quam. Nulla ac turpis pretium, gravida mauris vitae, interdum arcu. Aenean porttitor, justo a consectetur iaculis, neque est varius nisi, a vulputate eros elit ac justo. Etiam elementum ipsum sit amet dignissim lacinia.




The little magic behind it is a radio button before each tab. By nature of how radio buttons work, when one radio is checked, it's the only one checked, which makes then useful for out TabbedPanel, which will only show one tab at time.

<input type="radio" name="tabs" id="tab1" checked>
<div>
    <!-- Content tab 1 -->        
</div>

<input type="radio" name="tabs" id="tab2">
<div>
    <!-- Content tab 2 -->          
</div>

<input type="radio" name="tabs" id="tab3">
<div>
    <!-- Content tab 3 -->
</div>

This selector will select a div that it's right after a checked radio button

input[type="radio"]:checked+div{
    /* SHOW TAB */
}

But we don't want to show the radio buttons, so we hide then using CSS. But, there's a problem how we are supposed to check a radio button if it's hidden? The answer is a Label. A label let us refer to another element even if it's hidden, so that's what we are using as Tab buttons. The good thing is that allow us to place the tabs in any order we want, also put text and icons inside, even outside the tabbedPane.

<div class="tabBar">
    <label for="tab1">Tab 1</label>
    <label for="tab2">Tab 2</label>
    <label for="tab3">Tab 3</label>
</div>

The full markup is something like this

<div class="tabbedPanel">
    
    <div class="tabBar">
        <label for="tab1">Tab 1</label>
        <label for="tab2">Tab 2</label>
        <label for="tab3">Tab 3</label>
    </div>
    
    <div class="tabs">
        
        <!-- TAB 1 -->
        <input type="radio" name="a" id="tab1" checked>
        <div>
            <h1>Tab 1</h1>
            <p>Content</p>
        </div>
        
        <!-- TAB 2 -->
        <input type="radio" name="a" id="tab2">
        <div>
            <h1>Tab 2</h1>
            <p>Content</p>
        </div>
        
        <!-- TAB 3 -->
        <input type="radio" name="a" id="tab3">
        <div>
            <h1>Tab 3</h1>
            <p>Content</p>
        </div>
        
    </div>
    
</div>

This is more or less of what like the CSS would be

.tabbedPanel{
    display: table;
}
.tabbedPanel .tabBar{
    display: table-row;
    height: 0;
}
.tabbedPanel .tabBar label{
    display: inline-block;
}
.tabbedPanel .tabs{
   display: table-row;
   height: auto;
}
.tabbedPanel .tabs > input[type="radio"]{
    display: none;
}
.tabbedPanel .tabs > div{
    height: 100%;
    overflow: scroll;
}
.tabbedPanel .tabs > input[type="radio"]:not(:checked)+div{
    display: none;
}
.tabbedPanel .tabs > input[type="radio"]:checked+div{
    display: table-row !important;
}

Adding some quick look and feel

/**** Visual ****/
.tabbedPanel{
    border: 1px solid grey;
    height: 300px;
    width: 300px;
}
.tabbedPanel .tabBar{
    background: #F0F0F0;
    font-family: Helvetica, Arial, sans-serif;
}
.tabbedPanel .tabBar label{
    cursor: pointer;
    
    background: #C0C0C0;
    
    border: 2px outset #CCC;
    border-bottom-color: transparent;
    border-radius: 3px 3px 0 0;
    
    padding: 0.5em;
    padding-top: 4px;
    padding-bottom: 4px;
    
    margin-top: 3px; 
    margin-right: 1px;
}
.tabbedPanel .tabBar label:first-child{
    margin-left: 5px;
}
.tabbedPanel .tabBar label:hover{
    color: #38f;
}
.tabbedPanel .tabBar label:active,
.tabbedPanel .tabBar label.active{
    color: blue;
    background-color: #DDD;
    border: 2px outset #BBB;
    border-bottom: 2px solid transparent;
}
.tabbedPanel .tabBar label:focus{
    outline: 2px solid yellow;
}

.tabbedPanel .tabs > div{
    border: 2px outset #DDD;
}

I'm not sure how and if it can be used in a production environment. I can't answer that, but as-is, probably not. Somehow IE always finds its ways to not work with things properly, and that would kill every hope to let it going to production.

There's limitations. I couldn't figure out how to keep the current Tab button highlighted yet. Radio buttons require a name to work as a radio group, and labels require each radio button to have a unique ID.

Anyway, I hope you find it interesting, if you have any though on this, drop a comment.

5 comments: