Web Development

Creating a centered page layout with CSS

A reader recently asked how to create a centered page layout using CSS. The basic CSS technique is relatively simple, but not obvious. Here's what it takes to convert this old standby from tables-based layout to CSS.

A reader recently asked how to create a centered page layout using CSS. The effect the reader is looking for is similar to the layout achieved by centering an 800-pixel-wide table on a 1024-pixel-wide page. It's a widely used page layout that traditionally relies on nested tables to achieve the effect, so it's not surprising that the reader is looking for a way to replicate the effect with CSS.

The basic technique for creating a centered page layout in CSS is relatively simple, but it's not obvious. Let's see what it takes to convert this old standby from tables-based layout to CSS.

A centered layout, the old way

First, for the sake of comparison, let's look at an example of a page layout based on a centered table. The following code produces the example shown in Figure A.

<body>
<p>&nbsp;</p>
<table width="80%"  border="0" align="center" cellpadding="0"
cellspacing="10"
bgcolor="#FFFFFF">
    <tr>
        <td colspan="2"><h2 align="center">Header</h2></td>
    </tr>
    <tr>
        <td width="150px" valign="top"><h4>Navigation</h4>
            <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>
        </td>
        <td valign="top"><p>Main Content -- Love's not
time's fool...</p>
        </td>
    </tr>
    <tr>
        <td colspan="2"><hr />
            <p>Footer text -- Admit impediments...</p>
        </td>
    </tr>
</table>
<p>&nbsp;</p>
</body>

The <table> tag includes attributes that define the width as 80 percent of the page width and centers the table on the page. An empty paragraph preceding the table creates some vertical space between the top of the page and the top of the table. Another empty paragraph following the table does the same at the bottom of the page. The table itself contains two columns and three rows of cells. The cells in the top and bottom rows are merged to create header and footer panels, while the cells of the middle row create two columns—one for the main content and another for a navigation sidebar.

This is a very simple example of a technique that has been in widespread use for years. In real-world applications, the main table would typically contain other nested tables to create a more complex layout, but the added complexity doesn't change the basic technique.

Converting the layout to CSS

To convert this traditional table-based layout to CSS, you simply replace the table and the table cells with divs. One div replaces the table itself, and other divs replace the individual table cells that define the major layout elements, such as the header, footer, nav sidebar, and main content. The divs are each identified with a unique id that can be referenced with a CSS selector to create styling that applies specifically to the div with that id. The div that replaces the table is labeled id=outer, and the other divs are identified by their respective function.

Here's the revised XHTML code with divs instead of a table:

<body>
<div id="outer">
    <div id="header">
        <h2>Header</h2>
    </div>
    <div id="nav">
        <h4>Navigation</h4>
        <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 id="main">
        <p>Main Content -- Love's not time's fool...</p>
    </div>
    <div id="footer">
        <p>Footer text -- Admit impediments...</p>
    </div>
</div>
</body>

Notice that all the presentation formatting that was previously included in the <table> and <td> tags has been removed. The empty paragraphs before and after the table are gone as well. CSS styling will handle all the formatting and spacing.

Here's the CSS code that styles the page as a centered layout similar to the tables-based page above:

body {
    background-color: #999999;
    font-size:12px;
    font-family:Verdana, Arial, Helvetica, sans-serif;
}
div#outer {
    width: 80%;
    background-color:#FFFFFF;
    margin-top: 50px;
    margin-bottom: 50px;
    margin-left: auto;
    margin-right: auto;
    padding: 0px;
    border: thin solid #000000;
}
div#header {
    padding: 15px;
    margin: 0px;
    text-align: center;
}
div#nav {
    width: 25%;
    padding: 10px;
    margin-top: 1px;
    float: left;
}
div#main {
    margin-left: 30%;
    margin-top: 1px;
    padding: 10px;
}
div#footer {
    padding: 15px;
    margin: 0px;
    border-top: thin solid #000000;
}

Figure B shows the result—a centered page layout executed with CSS.

Analyze the CSS code

The body style is unchanged from the table-based design. It just sets the background color and default text font and size.

The div#outer style is the one that holds the key to this technique. This is the styling for the div that creates the centered box which serves as the container for the rest of the page content--the div that replaces the table. The width: 80% rule sets the width of the div, just as the corresponding attribute of the table tag set the width of the table. Similarly, the background-color:#FFFFFF rule creates a white background for the div like the bgcolor="#FFFFFF" attribute did for the table. The margin-top: 50px and margin-bottom: 50px rules replace the spacer paragraphs with top and bottom margins for the div itself.

The key to this technique is proper centering of the outer div. The challenge is that there is no align="center" attribute for a div like there is for a table. You could use text-align: center for the div's parent element (in this case, the <body> tag) to center the outer div. However, although most browsers will use that alignment for block-level elements, such as divs, in addition to text, it's arguably a misuse of the text-align attribute and leads to complications as you create additional styles to reset normal text alignment back to left.

The proper way to center a block-level element with CSS is to set margin-left: auto and margin-right: auto. This instructs the browser to automatically calculate equal margins for both sides, thus centering the div. The border: thin solid #000000 rule adds a border around the outer div, just because it's easy to add with CSS but difficult to accomplish with tables. The rest of the CSS code styles the divs for the header, footer, nav, and main content.

The div#header and div#footer styles set margins and padding for those divs. In addition, div#header includes the text-align: center rule to center the header text, and div#footer includes the border-top: thin solid #000000 rule to create a border along the top edge of the div to replace the horizontal rule above the footer in the table-based layout.

The div#nav and div#main styles create the two columns in the middle of the centered box. In the div#nav style, the float: left rule pushes the div to the left side of its parent element (the outer div), and the width: 25% rule sets the div's width to 25 percent of the parent element. With the nav div floated to the left and limited to a set width, it leaves room for the main div to move up to the right of the nav div, thus creating the two-column effect. The div#main style includes the margin-left: 30% rule to keep the main text aligned in a neat column instead of spreading out below the nav column. The main div's left margin is set to a value slightly larger than the width of the nav div. I cover the technique for creating columns with floats in more detail in my column "Use CSS floats to create a three-column page layout."

5 comments
kcaron
kcaron

This was totally informative. Very good. I can see clearly now. It really explained the process to center my sites. Next step (for me) is to apply the CSS outer DIV to a Expression Web document. The rest will probably be self explainable.

GVC2031
GVC2031

Good article, good information. I'm new to CSS and this is an excellent introduction. One question: is it possible (in this example) to have a footer that aligns to the bottom of the browser window regardless of the length of the navigation and main divs?

oddacorn
oddacorn

If you're like me and you create your web pages by writing your markup in a text editor, you may be in the habit of just starting with an tag. However, this example wouldn't work for me in IE7 until I added, at a minimum, "" at the top of the document. Of course you can include all the XHTML and dtd stuff, too, if you want. Firefox (v2) rendered the page fine without the additional info, but it looks like I'll be adding the DOCTYPE header to all of my pages from now on. Nice article, by the way. I'm going on a tag hunt very soon! Todd Corson Houston, TX