This article originally appeared in the Design & Usability Tactics newsletter. Click here to subscribe automatically.
Developing attractive and effective page layouts with CSS is an ongoing challenge. A recent project required an interesting combination of techniques in order to achieve the design objectives, and combining those techniques in the same layout presented some challenges. The biggest one was finding a solution that works—not just in theory—but across multiple browsers in the real world. The solution, though relatively simple in retrospect, required considerable trial and error to achieve.
The page layout (Figure A) consists of a header over a two-column body, with a footer at the bottom. It's a liquid layout that automatically resizes with changes in the browser window, and the major layout elements are centered on the page.
The header, which includes a logo, a picture, and a navigation bar, is what puts an interesting wrinkle in this layout. The logo is flush left, while the picture and navbar are flush right. This allows the header to expand and contract in width while remaining flush with both sides of the body area below. The navbar extends under the logo to tie the left and right sides together.
The body area includes a fixed-width sidebar column on the left and a variable-width main column to the right. The footer at the bottom of the body area spans the full width of both columns.
To position all those elements properly, I create separate divs for each of the layout elements (logo, picture, navbar, sidecol, maincol, and footer) plus two wrapper divs: one (bodywrap) to enclose the sidecol, maincol, and footer divs, and another outer wrapper (master) around everything to allow for centering the layout on the page. The various divs use a combination of static, relative, and absolute positioning.
Here's the XHTML markup for the example page in Figure A:
<div id="navbar">Navbar items go here</div>
<div id="sidecol" >
<li>Let me not to the marriage of true minds</li>
<li>Admit impediments; love is not love</li>
<li>Which alters when it alteration finds</li>
<li>Or bends with the remover to remove</li>
<li>Oh, no, it is an ever fixed mark</li>
<p>That looks ... height be taken.</p>
<p>But bears ... alteration finds.</p>
<p>Whose worth's ... to remove.</p>
<p>Footer text goes here </p>
Here's the CSS code that makes the layout work:
font-family: Verdana, Arial, Helvetica, sans-serif;
border-bottom: solid #000000 2px
padding: 10px 0px;
Centering the layout
The body style zeros out the margins and padding, sets the background color, and establishes default fonts. The text-align:center rule is for the benefit of IE5.5/Mac and allows that browser to center the layout elements on the page.
The #master style formats the outer wrapper div, which provides a container for the other elements, sets the overall margins, and centers the layout. The position:relative rule makes sure the absolutely positioned child elements are placed relative to the master div instead of the full page. The width:90% rule, along with the margin-left:auto and margin-right:auto rules, centers the layout with a small space on each side, while the margin-top:20px rule adds a little space at the top of the page. The text-align:left rule resets the default text alignment that was changed in the body style.
Note that the background-color:#006600 rule creates a dark green background for the master div, but you won't see any of that color in the sample page. The master div collapses to no height because the div contains no text or other divs that are part of the normal flow—all the child elements are (or are contained within) absolutely positioned divs, which exist outside the normal page flow. However, the div still does its job of providing a position reference for its child elements.
Constructing the header
The #logo, #picture, and #navbar styles each include the position:absolute rule along with size (i.e., width:200px, height:125px) and position (i.e., top:0px, left:0px) settings. A background-color rule in each style makes the divs visible in the example, but only the navbar contains a background in the real page layout.
Note that the positioning of these divs' is relative to the "master" container div. Therefore, the top:0px and left:0px rules position the logo div in the upper-left corner of the master div, not the upper-left corner of the page.
The width:100% rule in the #navbar style makes the navbar the full width of its parent element (the master div) and the border-bottom:solid #000000 2px rule adds a black horizontal line to the bottom of the div, which helps pull the left and right sides of the header together. The #navbar style also includes rules to make the text flush right (text-align:right) and center it vertically (line-height:35px, which is the same value as the height of the div).
Using absolute positioning for the logo, picture, and navbar allows you to position those elements against the left and right sides of the master div, regardless of its resizing. Floats, on the other hand, will collapse and drop down the page if the browser window becomes too narrow. Absolute positioning is also necessary to allow the navbar (and sometimes the picture) to extend behind the logo. This is an important consideration because the logo's background in the real Web site is transparent, allowing the navbar and picture to show through. The left sides of those elements are graduated to blend into the background behind the logo.
Building the body
The #bodywrap style formats the container div for the remainder of the page—the sidebar column, the main content column, and the footer. Like the header elements, it's absolutely positioned (position:absolute) relative to the master div. It doesn't have a fixed size so it can expand with its contents, up to the maximum width of the parent (master) div. The margin-top:150px rule pushes the bodywrap div below the header with a little room to spare. A top:150px rule would do the same thing, but margins seem to work more reliably. The padding:20px shortcut rule sets equal padding on all sides of the div. That works for this example, but you could also use margin settings on the child elements to accomplish the same thing. Another option is to add a background image to this wrapper div to create a full-height background for the sidebar column.
The #sidecol style establishes the fixed-width sidebar column with the width:200px rule and floats it to the left (float:left). Floating the sidecol div allows the maincol div to fill the space to the right of the sidecol rather than positioning it below the sidecol div. The style also includes settings for the background color, bottom margin, and padding, but none of these settings affect the technique.
The #maincol style formats the main content column. The margin-left:230px rule creates space for the 200-pixel-wide sidebar column, plus a comfortable gutter, and keeps the content from flowing into the space below the sidebar. The background color, bottom margin, and padding settings are just for appearance. In a real application, you'd probably add other rules to this style to format the contents of the column.
Finally, the #footer style formats the div at the bottom of the page. The width:100% rule makes the div the full width of its parent element (the bodywrap div, which is the full width of the master div). The clear:both rule ensures that the footer is placed below both of the other columns by specifying that it be clear of other elements on both sides. Note that the clear property applies to peer-level elements within the same parent element (the bodywrap div), not to other elements outside the parent. The other rules in the #footer style are for the appearance of the sample and are optional.
Essentially, this layout consists of absolutely positioned divs within a relatively positioned div that is centered on the page. Using absolute positioning provides good control over the placement of those elements, but it leaves the container div empty of any content that is in the normal flow.
As a result, the master div does not expand vertically to surround the other page elements as you might expect. That's no problem for this particular layout, but it does create a few surprises that could impact derivations of this layout.
For example, the background color from the bodywrap div extends all the way to the bottom of the page. You might expect to be able to change that by adding a bottom margin to the master div since it seems to encompass the bodywrap div, but it doesn't work because the master div is just a horizontal line near the top of the page and the absolutely positioned divs extend out the bottom of their container.