Tabbed Browsing with CSS2

Visited 652 times | Submited on 2007-10-05 16:40:49

So you've created one sweet web application, and you're very proud of the functionality, but the User Interface is somewhat lacking. Hey, don't worry, it happens to all of us. We are programmers after all, not UI designers! But don't despair; this tutorial will show you how to separate the pages of your application into ergonomically distinct chunks, by the use of CSS tabs. That's right, CSS, no tables involved!

It has become a very established fact that tabs are an easy way to separate pages or different areas of a website. If done properly, they can be very aesthetically pleasing and intuitive to use. You can prevent users from ever having to ask “umm, where's the _______ feature?”, because it will very obviously be one of the tabs. And not only that, but you can transcend the stereotype of a programmer and deliver something that works AND looks good!

For the sake of this example, I'm going to assume that you have a few different pages here, and they have very basic names, such as 'news', 'photos', and 'users'. I'm going to throw them into a very basic array for simplicity sake. We will use each item of the array to display a distinct tab, to show an icon, and to provide a link. For your own use you can make this as complicated as you want. In one application that I built, I used a multidimensional array for the sake of being able to control access based on privileges, but we don't need all that for the tutorial.

The Code

OK, to start off with, let's create the array. I'm using ASP syntax for this; feel free to translate it however you wish:

<%
dim arTabs( 5 )
arTabs( 0 ) = "home"
arTabs( 1 ) = "events"
arTabs( 2 ) = "news"
arTabs( 3 ) = "photos"
arTabs( 4 ) = "users"
arTabs( 5 ) = "admin"
%>

Now that we have the array, here's what needs to be accomplished. We're going to have one main layer to hold all the tabs. We will not use any tables. Tables are bad. Tables are the enemy. OK, maybe that's a little extreme, but truthfully this is not what tables should be used for, so we won't use them.

We'll have one layer (div) called navTabs, and loop through the array to output each item into its own little box, which we'll style into a tab!

Here we go:

<div id="navTabs">
<%
dim theClass, thisPage
thisPage = Request.ServerVariables("SCRIPT_NAME")
thisPage = replace( right( thisPage, len( thisPage ) - inStrRev( thisPage, "/" ) ), ".asp", "" )

This little piece is important. Working from the inside out, it first strips out the filename from after the last “/”. So if the URL is '/webapps/myapp/admin/users.asp', the resulting string is just 'user.asp'. Then we take that, and chop off the file extension, which is '.asp' in this case. The result is now just 'users', which you should recognize as one of the items in the array. That is important, as you'll see in a second.

for i = 0 to uBound( arTabs )
if thisPage = arTabs(i) or left( thisPage, len( arTabs(i) ) ) = arTabs(i)
then
theClass = "on"
else
theClass = "off"
end if

This is where the location identification takes place. It's obvious that if the current array item matches the current page, then we should set that tab item to be 'on'. However the second part of the 'if' statement might not make sense to you. It is there so that you can have multiple pages use the same tab. If I have pages that all work on users, I would want them all under the users tab. So I might create a generic users.asp, then maybe a users_password.asp, and perhaps a users_info.asp. As the first portion of the filename matches the array item, they all cause the 'users' tab to be active.

response.Write("<div class=""tab" & theClass & """ onclick=""javascript:window.location='" & arTabs(i) & ".asp'"">")

You'll notice I'm not anywhere outputting an anchor link. This is because I want the entire tab to appear as a link. So I set the onclick handler to send the user to the page, and as you'll see in the CSS, I set the cursor to a hand, to simulate a link.

Response.Write("<img src=""" & arTabs( i ) & ".gif"" align=""absmiddle"" />&nbsp;")

Response.Write( replace( arTabs(i), "_", " " ) & "</div>" & vbCrLf )

Here I've inserted an icon to enhance the usability, and then the name of the tab. The icon is just a gif with the same name as the array item, for the sake of simplicity. I didn't include any dimensions to the image, in case I want to quickly swap them down the road, or in case some of them are slightly different. Now we'll finish off the loop and I'll get into the CSS.

next
%>
</div>

The Style

Because we're using DIVs, which by default have a 'block' display, the output so far will look like this (assuming you have the icons in place):

cook

Not quite tabs. But now let's add a little style! Don't forget of course to add in the style declaration above the tab output coding!

<style>
#navTabs {
font-family: verdana;
padding: 0px 0px 0px 15px;
margin: 0px;
width: 100%;
height: 30px;
vertical-align: middle;
border-color: #333333;
border-style: solid;
border-width: 0px 0px 2px 0px;
}

So here we've set up the initial style of the tab bar, with the height, width, and font. The two most important declarations are the left padding to set an initial little indentation, and the bottom border of 2 pixels.

.tabon, .taboff {
height: 30px;
cursor: pointer;
cursor: hand;
display: inline;
overflow: hidden;
vertical-align: middle;
font-size: 11px;
padding: 6px 2px 0px 2px;
margin: 0px 2px;
border-color: #333333;
border-style: solid;
border-width: 1px 1px 0px 1px;
}

These are the common styles for both kinds of tabs. The cursor is set to emulate a link, the margin is set to separate each tab apart by a couple of pixels, and the borders are set. Very important is the changing of the display to 'inline', which enables them all to peacefully coexist on the same line, side-by-side. The vertical-align attribute doesn't really work as you or I would expect, so instead I employ the use of top padding to bump the image and text down closer to the middle of the tab.

.taboff {
color: #666666;
background: #dddddd;
}

Here we make the inactive tabs look inactive. We make the font a little more faint, and the background gray.

.tabOn {
font-weight: bold;
position: relative;
top: 2px;
background: #ffffff;
border-width: 2px 2px 0px 2px;
}

And this is the magic that makes a tab 'active'. We make the font bold to stand out, the border a bit thicker, and then move it down 2 pixels to give the illusion that it's flowing into to the border, and it's attached to the bottom part of the screen. Make sure you set the background color, otherwise you'll still see the bottom border, and the illusion won't really work.

After all is said and done, Here's what the finished product should look like:

cook

Pretty, huh?

Conclusion and All the Code

So you've seen that with a minimal amount of code, you can generate ergonomic, table-less tabs. And we did it all with a very basic array iteration, and a bit of CSS. This will no doubt increase the usability of your application ten-fold.

There is a chance that you're not quite satisfied with the flat-looking tabs, despite their advantages of easy configuration and fast loading. That's probably because you've seen tabs out there that look quite fancy, employing the use of 3D-looking buttons (like www.no-ip.com). Well, if you're interested in graduating to the next level of tabbing, stay tuned for my next article, which will explain how to create the 3D tabs in FireWorks, slice them up, and apply them to your tab structure in an extremely flexible and manageable way.

But until then, have fun with your new knowledge of table-less tab creation!

All the Code:

<style>
#navTabs {
font-family: verdana;
padding: 0px 0px 0px 15px;
margin: 0px;
width: 100%;
height: 30px;
vertical-align: middle;
border-color: #333333;
border-style: solid;
border-width: 0px 0px 2px 0px;
}
.tabon, .taboff {
height: 30px;
cursor: pointer;
cursor: hand;
display: inline;
overflow: hidden;
vertical-align: top;
font-size: 11px;
padding: 6px 2px 0px 2px;
margin: 0px 2px;
border-color: #333333;
border-style: solid;
border-width: 1px 1px 0px 1px;
}
.tabOn {
font-weight: bold;
position: relative;
top: 2px;
background: #ffffff;
border-width: 2px 2px 0px 2px;
}
.taboff {
color: #666666;
background: #dddddd;
}
</style>
<%
dim arTabs( 5 )
arTabs( 0 ) = "home"
arTabs( 1 ) = "events"
arTabs( 2 ) = "news"
arTabs( 3 ) = "photos"
arTabs( 4 ) = "users"
arTabs( 5 ) = "admin"
%>
<div id="navTabs">
<%
dim theClass, thisPage

thisPage = Request.ServerVariables("SCRIPT_NAME")
thisPage = replace( right( thisPage, len( thisPage ) - inStrRev( thisPage, "/" ) ), ".asp", "" )

for i = 0 to uBound( arTabs)

if thisPage = arTabs(i) or left( thisPage, len( arTabs(i) ) ) = arTabs(i)
then
theClass = "on"
else
theClass = "off"
end if

response.Write("<div class=""tab" & theClass & """ onclick=""javascript:window.location='" & arTabs(i) & ".asp'"">")

Response.Write("<img src=""" & arTabs(i) & ".gif"" align=""absmiddle"" />&nbsp;")

Response.Write( replace( arTabs(i), "_", " " ) & "</div>" & vbCrLf )

next
%>
</div>

By Justin Cook
Source: devarticles.com



Add your comment

Name:(required)
E-mail address:(optional)
Comment:(required)
Repeat the number for validation: (required)

Browse by Tags:


Related Articles:

Text Link Ads

Statistics

Total 296 articles submitted
Latest submission at January 28, 2008 15:13

Feedback

Use this email below to send us your suggestions and feedback. We value your opinion.
info (at) theitarticles.com