Developer

Creating a fixed-width layout with CSS

Columnist Michael Meadhra shares his tips for building fixed-width, CSS-based page layouts. This approach better handles content that includes lots of large images and other elements that don't flow well in a liquid layout.

This article originally appeared in the Design & Usability Tactics newsletter. Click here to subscribe automatically.

Several of my recent columns covered various aspects of executing two- or three-column page layouts with XHTML and CSS. So far, all of the examples have been liquid layouts (i.e., layouts that automatically expand and contract to fit within the width of the browser window). Now it's time to consider the other major page layout approach: the fixed-width layout.

Many Web builders prefer using fixed-width page layouts for page design because they produce precise and predictable results. This approach closely mimics print layout, which is a significant comfort factor for designers and visitors alike; it's also the best way to handle content that includes lots of large images and other elements that don't flow well in a liquid layout.

From table to div

For years, designers would create fixed-width page layouts with tables. The table's columns and rows are a passable analog of the designer's layout grid, so it's not surprising that designers adapted HTML tables for use in page layout.

However, table-based layouts have significant problems. Besides the fact that it's semantically improper to use tables for layout, the resulting code is messy, hard to read, and even harder to maintain—especially when it includes merged table cells and nested tables.

Using divs for page layout works much better. In addition to the karmic goodness of following the recommended best practices, leaner code loads faster and is easier to work with.

The formatting attributes of tables and table cells lend themselves to fixed-width layouts by making it fairly easy to specify the sizes of those elements. But you can accomplish the same thing with divs by giving divs exact dimensions and using absolute and relative positioning to place those divs on the page.

A fixed-width example

Figure A shows a typical fixed-width layout consisting of a header at the top, a three-column content area (a main content column flanked by two sidebars), and a footer at the bottom of the page. All of the elements are fixed widths; they do not resize with changes in the browser window.

The following XHTML markup produces the page shown in Figure A. (The content is truncated for the sake of brevity.)

<body>
<div id="head">
    <h1>header</h1>
</div>
<div id="columns">
    <div id="side1">
        <h3>side1</h3>
        <ul>
            <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>
        </ul>
    </div>
    <div id="content">
        <h2>main content</h2>
        <p>That looks on tempests ... his height be taken.</p>
        <p>But bears it out ... alteration finds.</p>
        <p>Whose worth's unknown, ... the remover to remove.</p>
    </div>
    <div id="side2">
        <h3>side2</h3>
        <ul>
            <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>
        </ul>
    </div>
</div>
<div id="foot">
    <h3>footer</h3>
    <p>Or bends with ... height be taken. </p>
</div>
</body>

Here's the CSS code that styles the page as a fixed-width layout.

body {
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 12px;
    margin: 0px;
    padding: 0px;
}
h2,h3 {
    margin-top: 0px;
    padding-top: 0px;
}
div#head {
    position: absolute;
    width:750px;
    height:100px;
    left:0px;
    top: 0px;
    background-color: #FFFF66;
}
div#columns {
    position: relative;
    width: 750px;
    top: 100px;
    background-color: #CCCCCC;
}
div#side1 {
    position:absolute;
    width:150px;
    top: 0px;
    left:0px;
    background-color: #FF6666;
}
div#content {
    position: relative;
    width: 450px;
    top: 0px;
    left: 150px;
    background-color: #999999;
}
div#side2 {
    position:absolute;
    width:150px;
    top: 0px;
    left: 600px;
    background-color: #00FF66;
}
div#foot {
    position: relative;
    width: 750px;
    clear: both;
    margin-top: 100px;
    background-color: #99FFFF;
}

Deconstructing the code

The markup isn't that remarkable—it's just divs around each of the major page elements (the header, footer, sidebars, and main content). Each div has an id that the corresponding CSS style can address. There's just one extra div (div id="columns") surrounding the three-column content area. That's necessary to push the footer down below the longest of the three columns in Internet Explorer.

As usual, the CSS code does all the heavy lifting. First, it does some housekeeping. The body style zeros out the page margins, and the h2,h3 style removes the default spacing above those heading styles. Otherwise, there'd be a margin around the layout, and the headings would create a blank space above the main content and footer in some browsers (e.g., Netscape and Mozilla).

The div#head style sets an explicit height and width for the header div. The header is explicitly positioned with the position: absolute, top: 0px, and left: 0px rules, which position it at the top-left corner of the page. The position: absolute rule is important because positioning attributes (top, left, right, bottom) are ignored for elements with normal (static) positioning. However, remember that any absolutely positioned elements are removed from the normal page flow, and elements that are part of the flow will be positioned on the page as if the absolutely positioned elements didn't exist.

The div#columns style formats the div that serves as a container for the three columns. It uses position: relative to create an element that's part of the normal page flow (it can expand and contract with its content and influence the positioning of other elements), but it can be offset from its normal position. The top: 100px rule provides the offset that pushes the columns container down to keep it from overlapping the header.

The div#side1 rule styles the first sidebar column. It sets the width of the column (width: 150px) and uses absolute positioning to place the column at the top-left corner of its parent element. The parent element is the column's div, which explains the top: 0px rule instead of the 100px setting that you might expect if the element was positioned relative to the body element. The div#side2 rule does the same for the right sidebar column. The only differences are the background color and the left: 600px rule, which positions the column to the right of the other two columns.

The styling of the main content column in the div#content style is similar to the other two columns. It sets an explicit width (width: 450px) and uses the left: 150px and top: 0px rules to position the column within its parent element (the columns div). The key difference is the position: relative rule. You use the relative positioning so the main content column can influence the size of its parent element (the columns div) and thus the footer element.

The div#foot style sets the width of the footer (width: 750px) and includes the clear: both rule to ensure that it follows below the other elements, not beside them. It uses relative positioning so its placement on the page is determined by the flow of the other elements, which in this case is the columns div. The margin-top: 100px rule is an important detail that prevents the footer from overlapping the columns above. Those columns are offset from their normal position in the page flow in order to make room for the absolutely positioned header, and the footer needs a corresponding offset.

A centered variation

Perhaps the most common major variation on the fixed-width page layout is a fixed-width block that floats in the middle of the browser window instead of being affixed to the left side. You can achieve that effect easily by adding a wrapper div around the rest of the markup, just inside the body tags, and creating a CSS style to center that div.

For example, Figure B is the result of adding one tag (<div id="wrapper">) and a corresponding CSS style to the markup for Figure A. Here's the CSS code for the added style:

div#wrapper {
    position:relative;
    margin-left:auto;
    margin-right:auto;
    top: 20px;
    width:750px;
    background-color: #CCCCCC;
}

This technique works because all the layout divs are positioned relative to their parent elements. In Figure A, the parent element for the head, columns, and foot divs is the body tag, but in Figure B, it's the wrapper div. This centering technique is explained in more detail in "Creating a centered page layout with CSS."

Editor's Picks