dcsimg
By Rogelio Vizcaino Lizaola (rojovizcaino@hotmail.com)

In Evolution of a Home Page Andy King threw down the gauntlet, challenging readers to duplicate WebRef's tabled home page in CSS. Kwon Ekstrom came up with a solution, which worked in a number of browsers. After investigating his solution, I found a few problems with his design, and thought I'd improve on his design. What follows is my attempt to duplicate WebRef's table-like layout using CSS, while avoiding some of the bugs and problems found in other implementations.

The goal is to create a CSS layout that resembles exactly the actual WebReference layout made with tables but not just visually, it should behave as well with small window sizes and large fonts.

The target browsers are all the generation five and up browsers, for both Windows and Macintosh platforms, and we are looking to use the same style rules for all of them, this constrain makes the task more difficult and the final code larger and complex than it would be for a browser with good compliant CSS level2 like Netscape 6. So, we cannot use does futures that aren't supported for all browsers and some times the necessary workarounds to solve bugs or other problems yield in a not so straight forward use of CSS.

The WebReference home page has six big blocks that holds and organize the content:

Disregarding the top navigation bar, the advertisement block and the "Tip of the day" we have a three column layout. We can ensure that the middle column is going to be the one with more content, and there for, the height of the document will be dictated by this block, and the three columns should be the same size. Notice that there is a white gap that separates the left column from the main area and other one that does the same for the right column, this separators have the same width than the space from the browser window edges to the document.

Lets make a simple three column layout with gaps between the columns, with the center column content dictating the height of the all document. We will start with four divs and their respective style declarations.

  1. First we set the margin and padding from the body element with the next statement to give the wanted aparence, notice that we need to set the padding because Operas default is different from zero. Also, we set the background color to white, because Netscape 6 for Macintosh default background color is gray.
    
    body {
    
      margin:9px 9px 0 9px;
    
      padding:0;
    
      background:#FFF;}
    
    
  2. Now we put our first element, a div that we will give an id attribute value to "level0". The only style definition for this element will be a background color, the color we want for the left column. Take a look
  3. We nest a second div inside "level0" and give it the id "level1". This new div it's going to make the visual layout for the left column and left separator. The left column area will be reserved using a left margin for "level1" and the separator using a left padding, so we will need to set the background color from "level1" to the desired color for the separator. Take a look
  4. We nest inside "level1" a div with id "level2". We only change the background color to this new div. Now we can see clearly the left column and its separator. Take a look
  5. We use the same technique, nest a "level3" div inside "level2" to get the visual layout for the right column. This time we will nest another div called "main" just to set its background color different from transparent, and so we can notice the columns and the separators. Take a look

We haven't made the code for the right and left columns content yet, just the visual layout, but we have illustrated the basic technique to display three columns and make them exactly the same height. So before discussing this issue lets put the top navigation bar and the advertisement block in place. We are going to nest inside "level1" and before "level2" a div with id set to "topBar", and inside "topBar" we nest another div with id set to "advBar". Take a look

We have by the moment three blocks where we can put some content, the main area, the top navigation bar and the advertisement block. Each one will be as high as its content demands, but we have constrain their widths so the blocks for the left and right navigation bars won't be invaded by the content in this div elements. Lets put in place the "Tip of the day" box using the float property so the content in the main area will flow around as needed, we put a div with id "tipDay" inside the "main" div, set the float property to right and declare its width to some value (be sure of declaring the width for all the elements with float set to other value than none). Take a look

Now lets tackle the problem on how to put the content on those bars. The more natural way of doing it would be to use the float property, but do to Opera and IE have rendering problems with this technique we need to relay on absolute positioning to get things done. The IE bug is minimal, and could be disregarded but no way to solve the Opera bug was found. Take a look to the links below for a description and example on this bugs. Buggy version on Opera Float bug Opera Float bug IE

Lets start with the left navigation bar doing a div with its id set to "lftBar". Since we are going to use absolute positioning, we have more freedom to choice the place where the left bar chunk of source code goes in. Could go inside "level0" before or after "level1" or even at the same nesting level than "level0" before or after, and this shouldn't make no difference if we chose the right reference frame and coordinates. At least IE5.5 has a bug that causes overlap when we try to use "level0" as our reference and top and left set to zero for "lftBar" ("lftBar" being child of "level0" and "level0" with position property set to relative), so we have to use the body element as our reference frame and set the top and left property from "lftBar" to the same value used for the body margins. Take a look Buggy version on IE Another buggy version on IE

For the right navigation bar we will use also a div with its id set to "rgtBar". The first thing to notice, is that we should insert this new div in a proper place to make its top edge, coincident with the main area top edge. So we insert it inside "level2" before or after "level3" set "level2" position property to relative to use it as our reference frame and for "rgtBar" we set position to absolute, top and right to zero and its width to the same value we used for the right margin of "level3". Take a look

This version has two problems in IE for Windows. The first one is that the "Tip of the day" box disappears although that the content in the main keeps flowing as if it was there. This rendering problem has a fast solution, we set the position property of "tipDay" to relative and we get back the proper rendering. The second problem for windows IE is that the right navigation bar horizontal position is misplaced, as far right as possible. To solve this problem we have to give to "level2" (the reference for "rgtBar") a width declaration. IE doesn't understand the keyword 'auto' for this property but understands 'inherit' in a particular way (not standard) and we can exploit this in our behalf. We set "level0" width to 100% and "level2" width to inherit, the trick is that IE will inherit the value from "level0" and the rest of the browsers will inherit the value 'auto' from "level1". If we declare directly width to 100% for "level2" we still have rendering problems. Take a look

It's time to do cleaning and put other elements that will point to problems that have to be worked out. First we will get rid of "level3" and pass all its style declaration to "main". This next example has a left border for the right navigation bar using the border-right property from "main" (remember that "level3" no longer exists). We add two headers to the main and some sample content and also some headers to the right bar with some style rules. At the bottom of the right bar we have placed A_Long_String header to show problems with large font sizes. The text inside this element can't be broke in different lines, so it will overflow if its wider passes the width set to the right bar. Go ahead and test it with different font sizes. Take a look

To prevent the overflow problem we will change some style declarations from "rgtBar" and "main" to a value expressed in relative units as "em". We have been using 143 pixels that would be about 9em's with the browser font size set to 12 points. One handy equivalency is 12pt = 16px. So we change now the values for width and margin-right from "rgtBar" and "main" respectively to 9em instead 143px. With this tweak we have a right bar that changes its width proportionally to the users desired font size value. Try it with large font sizes. Take a look

Depending on the browser the user has different ways to set the desired font size. The technique described above solves overflow problems for most of the possible user interactions but not all. We set now the "Tip of the day" box width in the same way and stick to the absolute units size for the left navigation bar, since it doesn't have overflow problems that brake the layout.

Now we are going to place the search form and text links into the top navigation bar. To insert the form we just give it a float right treatment and write the chunk of code as the first child of "topBar". We have to declare a width for this element since we are floating it, 10.5 em is a good value and note that we are using em units to let the input elements grow according to the browser selected font size. We also set the text alignment to right, since the form is a little wider than the space used by the input elements. We aren't done yet, so try it to see what are we going to solve next. Take a look

We need to set margins to zero to make the form vertical size as small as possible. For Netscape we have to add a line-height set to .7em statement to make the search button height the same size than the other input element, this statement doesn't change nothing for IE or Opera. The float its overlapping the advertisement block, and we can't aloud this because we are going to have a text link just below the search form but inside the advertisement block, so we set "advBar" clear property to right. Finally we set "topBar" width to 100% to solve a IE bug that breaks the layout and declare that the input elements from the top bar should have a font size of .8em, this way they will grow accordingly to the browsers font size. Take a look

Lets put the text links in place. There are five text links separated by bullets and wrapped by a b element, so this b element should be the second child of "topBar". Now, there is a strange bug in Windows IE 5.0 that flushes this links to the right. To deal with this problem we can wrap the b element with a div element and set its text alignment property to left or we can use the display property from the b element to convert it into a block element and then set the text alignment to left. We also set the font style and chose a good value for the line height so the text links are vertically centered. Take a look

In this step we are going to change the headers 'This is the main.' and 'This is the main2.' for 'WebReference.com: Dev the Web™' and 'Developer.com' respectivly, as this is the real content in the WebReference site. We are doing this because we are going to put a title to the "Tip of the day" box, and this title goes in the same dark colored header bar that holds the 'WebReference: Dev the Web™' text. To acomplish this we are going to use a div element that we are going to identify by "tipTit", this element should be the first child of "main" and have its float property set to right, again we need to set its width to some value and give it some font style attributes to have it vertically centered. The width used is 11em (the same width of "tipDay") and we also set text-align to right and the position property to relative, this solves a rendering problem in IE that we have talk about. The line-height property should be set to the same value used in the header to give the vertical centering. Take a look