Today's New Content
Search CMX

Advanced Search

Latest Free Content
View All
Free Content
Accessibility

Creating Liquid Faux Columns

By: Zoe Gillenwater

One of the most frequent layout issues that new CSS developers want to tackle is equal height columns. In table-based designs, this is easy because each cell in a row is tied together. The height of one affects the height of the others. However, in CSS-based designs, each div is an independent element and is only as tall as its content needs it to be. This means that if you use two divs to create a two column design, but your right column has more text in it, then your right column is going to be longer.

How, then, can you tell your divs to look at other divs on the page, figure out which one is the longest, and adjust its height to match? In CSS 2.1, you can use the table display properties to get your divs to act like table cells without really being table cells. Unfortunately, Internet Explorer doesn't support most of these properties, so this solution is impractical at the time being.

Luckily, some clever developers came up with a way to simulate the appearance of equal height columns without really having them: wrap the columns in a container div and assign it a background image that repeats vertically. When tiled down the page, it creates an image of columns, and the divs can simply be laid over the top. No one is the wiser!

This technique has come to be known as the "faux columns" technique after Dan Cederholm's article at A List Apart. In this article, he shows how to use a background image on the body to create the illusion of three equal height columns. Because the example layout he uses is fixed (meaning all the columns have rigid pixel-based sizes instead of liquid percentage sizes) and because background images themselves have fixed pixel dimensions, many readers mistakenly thought that the faux columns technique can only be used in fixed designs. Not so!

In this article, you'll learn how to use vertically tiling background images to create liquid equal height columns that can grow and shrink as you resize your window.

The Trick

The trick in creating liquid equal height columns is all in how you set up the background image. We'll start by making a simple two column design with the blue left column at 20 percent and the right pink column at 80 percent. This means that no matter what size our browser window is, we want blue to fill up the left 20 percent and pink to fill up the right 80 percent. It follows, then, that our background image should be blue on the left 20 percent of the image and pink on the right 80 percent.

We also know that our background image will need to be very wide – with such big monitors nowadays, there's no telling how large someone might be running their browser. So, we'll make the background image 2000 pixels wide just to be safe. Open up Fireworks and create a new document that is 2000 pixels wide by 10 pixels tall.

A little simple math tells us that 20 percent of 2000 is 400, so draw a 400 pixel wide rectangle and fill it with blue. Position this rectangle at the left of the document. To make the remaining 80 percent (1600 pixels) of the document pink, simply change the canvas color to pink. We now have an image that, when tiled vertically, will create the appearance of two columns: a thin blue one and wide pink one.

However, we don't want our left column width fixed at 400 pixels as it is in this background image. If we place it on the container as is, it doesn't adjust in size as the actual columns do when the window is resized.

The trick is in the background-position property. This property controls where the background image is placed in its container. If you use pixels or other fixed units to position the background image, it moves the top left corner of the image to that point in the box. However, when you use percentages, you position a point within the image itself, not the top left corner. This point is moved to the corresponding percentage point location in the box. So, if you set background-position to "20% 10%", the point 20 percent across and 10 percent down the image is placed 20 percent across and 10 percent down the box.


Image 1: A diagram of how the background-position property works with percentages. If the background image was larger than the box, it would be cut off on the left and top, instead of showing a gap.

Can you think of how this provides an easy way to center a background image? Just set the left-right value to 50 percent, and the browser will find the spot in the background image that is 50 percent of the way from the left edge and place this spot at the corresponding 50 percent spot of the box, centering the background image.

In our case, we want the blue part of the background image to only take up 20 percent of the window. The spot where the two columns will meet is 20 percent over from the left edge of the screen, and this is also where we want the edge of the two colors to be. So, we want to tell the browser to find the spot in the background image that is 20 percent from the left and position this spot 20 percent across the page so it will correspond with the meeting point of the two columns.

body {
  background: url(tile.gif) 20% 0;
}

In this case, I've placed the background image on the body, but it can be placed on any container div as well. Now the 20 percent spot of the image matches up with the 20 percent spot of the page, so as the browser window is resized the background image moves along with it. In the downloads for this article, open the file twocol.htm to see this in action.


Image 2: The background image does not resize, but just moves so more or less of it is exposed in the viewable area of the window.

If we wish to change our left column to 25 percent, for example, all we need to do is change that div's width in the style sheet, change the background position value, then edit our background image so that exactly 25 percent of it has our left column color.

Using Multiple Backgrounds

What if you want to have three columns, all liquid, and all equal height? In this case, a single shifting background image will not work, because the center portion needs to grow and shrink in size. In this case, you need to create multiple background images that can overlay one another to create the effect. This means we can't place the background image on the body; instead, we need two container divs, each with a tiling background image – one with the image for the left column, and the other with the image for the right.

Let's say we're trying to build the following design of three equal length columns, a partial header, and a full footer, all liquid:


Image 3: The design we want to accomplish using CSS.

We'll start by creating our background images. First create a new document in Fireworks that is 2000 by 10 pixels. Fill the left 20 percent (400 pixels) with a rectangle in color #990000. With the rectangle still selected, go to Texture on the Properties panel and select Crosshatch 3 to fill the shape with this pattern. If you zoom in closely you will notice that the pattern is partially cut off on the bottom, which means it will not tile correctly. With the rectangle deselected, click the Canvas Size button on the Properties panel. Change the 10 to 8 and click the top center button next to Anchor. This will crop the image from the bottom to eight pixels high, which is the height of one complete row of the diamond pattern. Now the spot in the pattern where it ends at the bottom matches up with the spot where it begins at the top, so it will tile seamlessly.


Image 4: The pattern at ten pixels high (left) versus eight pixels high (right). Cropped to eight pixels, it will tile seamlessly.

Open the Optimize panel and select GIF as your file format and Index Transparency. Use the eyedropper tool with the plus sign to select the white in the rest of the image as the transparent color. Export the image and save as left-bg.gif. (The source file for this image is provided in the downloads as left-bg.png.)

Our next step is to create the background image for the right column. Although it looks like a simple border, we need to use a background image to ensure that this "border" always extends to the bottom of the longest column. If we just set a border on the right or center columns, it would only extend as far as the content in that column. Using a background image to simulate a border enables us to create equal height columns.

Create a new document in Fireworks that is 2000 by 8 pixels (just to be consistent with our other image, but the height in this case is irrelevant). We want the right column to be 28 percent, which is 560 pixels, so drag a guide out to the 1440 pixel mark (560 pixels from the right). To create a guide, make sure your rulers are showing (if not, press CTRL/CMD+ALT+R), position your mouse over the vertical ruler, then click and drag out to the right. A green line should appear, which you can then drag to the 1440 pixel mark. You may want to zoom in to make sure you get right on the mark – these background images need to be precise!

Select the Line tool and set color #CCCCCC as the stroke color. Draw a vertical line up against the right side of the guide. Then, use the Optimize panel to set the file format and transparency options just like you did for the first image, and export as right-bg.gif. (See right-bg.png for the source file.)

Create a new (X)HTML document and style sheet. We need two wrappers to hold our two background images, so create those divs first.

<div id="wrapper1">
<div id="wrapper2">
</div>
</div>

In your style sheet, create the following selectors:

#wrapper1 {
  background: url(left-bg.gif) 20% 0;
}
#wrapper2 {
  background: url(right-bg.gif) 72% 0;
}

We've set the left background image to 20 percent because we want its 20 percent point to be placed 20 percent across the box. We've set the right background image to 72 percent because we want its 72 percent point to be placed 72 percent across, creating a 28 percent wide right column.

Because wrapper2 is nested in wrapper1, it covers it completely, but since we made most of wrapper2's background image transparent, we can still see wrapper1's background image through the transparent area. Because left-bg.gif, the background for wrapper1, is on the bottom in this case, we didn't need to make any of it transparent, but we did anyway so we could have the flexibility to lay either one over the other. If you prefer, you can assign right-bg.gif to wrapper1 and left-bg.gif to wrapper2 instead – the ordering here doesn't matter because they both will be the same width and height.

If you look at your page now, you won't see either of the background images, because so far the page has no content! Let's add that now. I'm going to use the float method outlined in John Gallant and Holly Bergevin's article The Theory of CSS Column Design: Source Order. If you aren't familiar with it, please look that article over first.

Add the following divs within wrapper2:

<div id="wrapright">
  <div id="header">header</div>
  <div id="center">center content</div>
  <div id="right">right content</div>
</div>
<div id="left">left content</div>

Then add the following selectors to your style sheet:

#wrapright {
  float: right;
  width: 80%;
}
#header {
  background: #fcc;
}
#center {
  float: left;
  width: 65%;
}
#right {
  margin-left: 65%;
}
#left {
  color: #fff;
  margin-right: 80%;
}

What this does is effectively divide the page into two columns first – wrapright and left – then further divides wrapright into two columns – center and right – to create our three columns. The header, which sits in wrapright, has its own background color assigned that simply overlays the tiling backgrounds below.

The center div is floated to the left within wrapright and given a width of 65 percent. This value may be puzzling at first, because we want our center column to be 52 percent wide (the space left over after the 20 percent left column and 28 percent right column). However, remember that this is 52 percent in relation to the window, and the width here is in relation to center's parent, wrapright, which is only 80 percent of the window. So, 52 percent is actually some unknown percentage of the 80 percent. If we put this into algebra terms, we get the following formula:

.52 = .8x
or
.52/.8 = x

So, to solve for our mystery percentage x we divide .52 by .8 and get .65, or 65 percent!

You want to end up with a nice even number here. If you end up with a fraction, such as 62.5, adjust your column widths until you can come up with an even integer. This is because fractional numbers are handled differently by different browsers, potentially causing overlaps. Thus, you should do these column calculations before you even create your background images. That's why I choose 28 percent for the right column – doing so made the center column 52 percent, which divided evenly into 80.

Now all our columns and backgrounds are set up. However, since we've used floats for our columns, the two wrappers won't actually contain them (remember that floats are removed from the flow of the document, so those wrappers don't know they exist), so our two backgrounds won't show. To get the wrappers to contain the floated columns, we'll use the generated content clearing solution described in John Gallant and Holly Bergevin's Clearing Floats, the Easy Way. Add these selectors to your style sheet:

.clearfix:after {
  content: ".";
  clear: both;
  height: 0;
  visibility: hidden;
  display: block;
}
.clearfix {
  display: inline-block; /* Fixes IE/Mac */
}
/* Hides from IE-mac \*/
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* End hide from IE-mac */

Then, apply this new class to your wrappers:

<div id="wrapper1" class="clearfix">
<div id="wrapper2" class="clearfix">

Add some paragraphs of text to each column and preview your document in a browser. You will now see three columns of equal length that grow and contract as you resize the window.

If you preview in a Gecko-based browser, you may notice that there is a gap above all three columns. This is due to the default top margins on the paragraphs that are within the columns, which escape out of the top. This phenomenon is a manifestation of margin collapsing and is actually correct behavior that works in your favor most of the time. In this case, though, it is obviously undesirable. The solution, however, is simple: get rid of the margins on the top of the paragraphs. Add this rule to your style sheet:

p {
  margin-top: 0;
}

If you have multiple paragraphs within each column, they will still be spaced out from one another due to their default bottom margin that we have not taken away. Keep in mind that headings also have default margins that can cause margin collapsing issues, so you may want your rule to look like this:

p, h1, h2, h3, h4, h5, h6 {
  margin-top: 0;
}

You now have an all liquid, three equal height column layout that should look like this:


Image 5: The finished product: three equal height liquid columns simulated using positioned background images.

Make sure you do not add padding to your columns. Doing so will increase the size they take up on screen. If you want to move the content of each column away from its edges, you will need to use margins on that content, or insert another div into each column that you apply a width or margins to and which wraps all of the content in it.

Summary

Here are the tricks you need to remember when creating liquid equal height columns:

Approximate download size: 180k


Keywords
CSS, style sheet, liquid, fluid, fixed, equal-height, columns, background position, tile, resize, grid