Easy Multi-Column Designs
Using CSS 2.1 Display Properties

- Part 1: Building the Page
- Part 2: IE Workarounds
- Part 3: Making it pretty
Part 1: Building the page
CSS 2.1 introduced a set of display properties that allow compliant browsers to display DIVs, as well as other elements, as if they were tables, table rows, and table columns. With the rise of MSIE 8, all major browser brands now support these properties. Since IE 8 is gaining market share over earlier versions, and with Windows 7 launching in October 2009 (with IE 8 as its default browser), it's a good time to embrace this methodology. Of course, IE 6 and IE 7 need to be addressed—but this can be done with a simple workaround using MSIE Conditional Comments.
Stable as a Table—without the Table
CSS table display allows us to create a perfectly stable multi-column design, with a flexible middle column and fixed-width sidebars, while avoiding the pitfalls and hacks you would encounter using CSS floats. You won't have to worry about issues such as negative margins, box-model calculations, extra structural elements, equal height columns, float drop, or float clearing.
CSS Table Display vs. Structural (real) Tables
CSS table display is not a substitute for structural table markup—nor does using CSS table display mean that you have gone over to the dark side and back to table-based layouts. All we are doing is using modern CSS methods to tell modern browsers how to display our perfectly standards-conformant markup. Structural tables, on the other hand, are still the correct choice when we need to display tabular data in a grid. Now, on with the lessons.
Marking up the layout with masthead and footer
We'll start with a blank new page, which Dreamweaver CS4 codes like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Untitled Document</title> </head> <body> </body> </html>
Edit your title to make it meaningful:
<title>PVII CSS Laboratory: 3-Column Flexible Layout - Hold the Hacks</title>
Make a new line between the opening and closing body tags and Enter the base structural markup, along with ID and Class Names:
<div id="masthead">
</div> <div id="wrapper">
<div id="firefox-bug-fix"> <div class="columns" id="c1"> </div> <div class="columns" id="c2"> </div> <div class="columns" id="c3"> </div> </div>
</div> <div class="footer"> </div>
CSS Insight: The wrapper and firefox-bug-fix DIVs are made necessary by Firefox bugs. According to CSS specifications, if an element is set to display: table-cell and there are no parent elements set to display: table and display: table-row, the browser will act as if those elements are actually there. The missing elements are referred to by the World Wide Web Consortium as anonymous elements. Firefox, unfortunately, does not get this right all the time so it is wise to structure your markup without relying on anonymous elements. This is why we wrap our columns inside the wrapper and firefox-bug-fix DIVs. As you'll see in a moment, the wrapper element is set to display: table, and the firefox-bug-fix element is set to display: table-row.
Note: If you change the ID values or class names from ours you will find it difficult to follow the CSS portion of this tutorial. If you want to change the naming convention, do so after you have finished the tutorial and make sure that if you change an ID or a class name, that you do so in both the markup and the CSS.
Add some content to your headings and paragraphs:
<body>
<div id="masthead">
<h1>Masthead</h1>
</div>
<div id="wrapper">
<div id="firefox-bug-fix">
<div class="columns" id="c1">
<h3>column 1</h3>
<p>Lorem ipsum dolor</p>
</div>
<div class="columns" id="c2">
<h2 class="topper">Center Column</h2>
<p>Lorem ipsum dolor</p>
</div>
<div class="columns" id="c3">
<h3 class="topper">column 3</h3>
<p>Lorem ipsum dolor</p>
</div>
</div>
</div>
<div class="footer">
<p>Footer</p>
</div>
</body>
Note: We've added just a few characters of content to ensure that the code fits comfortably in this page. You should add a bit more content so that you have something substantial to look at as you begin to style and preview your page.
Now it's time for CSS
Create a new CSS document and link it to your page. If you're not sure how to link a style sheet, place this code on a new line just above your closing </head> tag:
<link href="styles.css" rel="stylesheet" type="text/css" />
Adjust the name and path to match your CSS file name and its relative location.
Populate your style sheet with these rules:
body {
background-color: #FFF;
color: #000;
margin: 10px;
padding: 0;
min-width: 970px;
}
We set a min-width on the body element. This ensures that if the window is made narrower your layout will
remain flexible until it reaches a total width of 970px, after which the window will spawn a horizontal scrollbar. This prevents the center flexible column from getting so narrow that its contents become hard to read. You can change this value to suit your own needs.
#wrapper {
width: 100%;
display:table;
border-spacing: 0;
border-collapse: collapse;
}
This is your main layout container. Since this is a flexible layout, we set width to 100%. The display: table declaration makes the wrapper act like a table so that elements inside of it can be made to act like table rows or columns.
The border-spacing: 0 declaration works like the cellspacing attribute on a table tag. Since it's 0 (zero) we really don't need to declare it but it's nice to have in case you ever want to add spacing at a later date.
The border-collapse: collapse declaration instructs the browser to draw any borders you set on table columns or rows with no space between them and to collapse adjacent borders so that they appear as a single border.
If you wanted space between the borders of your columns and separate borders for each, you would set the border-collapse value to separate and you would set border-spacing to a value greater than zero.
#firefox-bug-fix {
display:table-row;
}
When you declare an element to display:table and then set a child (nested) element inside it to display: table-cell, the specificiation calls for browsers to imply that there is a table-row element surrounding the table-cell elements. All modern browsers get this correct—except for Firefox. While Firefox will behave on simple pages, more complex pages will be problematic. This rule, assigned to an inner wrapper will ensure that your page always displays correctly in Firefox.
.columns {
display: table-cell;
border: 1px solid #000;
vertical-align: top;
}
The .columns class is assigned to the center DIV and sidebar DIVs in our layout. The display: table-cell declaration instructs browsers to display the .columns DIVs as table cells—or <td> elements.
We set a 1px border around each column and set vertical-align: top (same as we would in a structural table) to ensure that each column's content begins at its column's top.
Note: The table-row property (similar to the <tr> element in a structural table) is implied by the browser. You can use the table-row property to create more complex layouts, but that's beyond the scope of this tutorial.
#c1 {
background-color: #326698;
color: #FFF;
padding: 20px;
width: 180px;
min-width: 180px;
}
#c1 is assigned as an ID to the first column, allowing us to set special properties for the first column only. We set a background-color, a text color, padding, a width and a min-width. The min-width value should match the width and is necessary to ensure that if any of your columns contain content that is too wide, this element will maintain its set width and not grow any smaller. You can change the width to any value you want, so long as it's in pixels.
#c2 {
width: auto;
padding: 20px;
}
This ID is assigned to the center column. This is our flexible column so width is set to auto. We also assign padding.
#c3 {
background-color: #D7D7D7;
width: 180px;
min-width: 180px;
padding: 20px;
}
#c3 is assigned as an ID to the third column, allowing us to set special properties for this column only. We set a background-color, a text color, padding, a width and a min-width. The min-width value should match the width and is necessary to ensure that if any of your columns contain content that is too wide, this element will maintain its set width and not grow any smaller. You can change the width to any value you want, so long as it's in pixels.
That's the end of Part 1. At this point, our page should now look like this in a browser (or Dreamweaver Live View):
Dreamweaver Design View, however, lacks complete support for CSS2.1 so your columns will display as rows. This is a Dreamweaver deficiency and should not discourage you from using modern CSS techniques.

