The Linux Page

3 columns with CSS


Often, when you build a website, you want columns.

Common designs include

  • Two columns, a content column and a column for different type of things such as menus, advertising, search form, etc.
  • Three columns, a content column and one column on each side with the menus, advertising, search form, etc.

In order to create a template with columns, one can use a table. Although rather easy to implement, there are problems with tables. (Specifically, with Drupal, FCKeditor does NOT work properly if you use a table. The width will improperly be computed. According to the author, the problem is really deep into the code of FCKeditor. So in other words it won't be fixed soon.)

The page attempts to explain how you can create a 3 columns CSS that works.

What we want to do

Presenting the columns named Left, Content (Squeeze), Right.
Figure 1. The left bar, content and right bar

Figure 1. above presents the feat. We can see a main DIV called Wrapper. That encompasses everything else. Within the wrapper you could also have a header and a footer.

There is the Container DIV (orange) that encompasses everything about the three columns. This ensures that you can have a header and a footer before and after. It is not required otherwise.

The Container includes three DIVs: the Left, Center and Right DIVs. All three use float: left; in their style. The float: left; is what generates the columns.

If you only use float: left;, however, the Left, Center and Right areas will be as small as possible in width. This is because the float keyword has the side effect of marking the blocks fixed. That makes them lose their usual width to the minimum/maximum width necessary to display their contents.

The Solution

Note that in Figure 1. the DIV were assigned a border. This means you cannot use the solution described here. Without borders, however, it will work. If you need to use borders, add another DIV within the Left, Center or Right areas and assign a border to that DIV instead (the Squeeze can have a border, but with Internet Explorer it may not work 100%.)

In Figure 1. we show that the Content includes a Squeeze area. One thing we can do with a DIV is assign it a width of 100%. This means the DIV uses the full width of the window.1

The idea is to make the Left, Center and Right floats. Force the width of the Left and Right bars to some specific size in pixels (i.e. width: 210px;). Then setup the Center DIV is defined with a width of 100%. To make the center still stay in the center, add side margins of -210px.

Column Width Margin
Left 210px 0px
Center 100% -210px
Right 210px 0px

This much gives you the effect you see in Figure 1. with the light green, blue and dark green boxes. Now we can see that the Center box overlaps over the Left bar and under the Right bar (i.e. because of the negative margins.)

So, to put content in the center, we now need another box inside the Center DIV and with margins equal to the opposte of the Center margins (i.e. +210px).

Column Width Margin
Squeeze auto 210px

Now you probably want to use the left side column to put a menu or other things where you need to be able to click with the mouse pointer. You can make that work by adding a z-index: 2; and position: relative;. The level to use on the z-index keyword will of course depend on the z-index of the center too. And if the center has a z-index, you may very well need to setup a z-index on the right column too.

That's it for the columns!

The next problem is that the Container DIV (and in effect, the Wrapper) do not include the floating blocks. Again, this is a problem with the fact that these blocks are automatically transformed into fixed blocks that are detached from their containers.

To fix this problem, we want to add another DIV after the columns that includes a clear: both; statement. This ends the effect of the float in regard to the containers. If you have a footer, you can do that in your footer.

The Code

Here I present the code with the inline style. It may be a good idea for you to have the styles in a CSS file and referencing it with identifiers or classes.

<div style="border: 3px #888888 solid;">
  <div style="border: 3px #ff8800 solid;">
    <div style="border: 3px #00ff00 solid; float: left; width: 210px; z-index: 2; position: relative;">
      Left (210px)
    <div style="border: 3px #0000ff solid; float: left; margin-left: -210px; margin-right: -210px; width: 90%;">
      <div style="border: 3px #ff0000 solid; margin-left: 210px; margin-right: 210px;">
    <div style="border: 3px #008888 solid; float: left; width: 210px;">
      Right (210px)
    <div style="clear: both;">
      Force enclosure to the bottom


This solution assumes that all columns but one have a known width.

Defining the height of the columns (i.e. for background colors or graphics) is very difficults. Most of the time, you create a design that assumes the 210px on the left and stops by the maximum width of the content. Then you have a design for the right column of a known height (you can always force the right column to be of a specified minimum height.)

There is a method one can use to make the columns the proper height. It requires you marking the column as very tall (i.e. 10,000 pixels) and adding a very tall bottom margin (i.e. -9,550px). You can also add some Javascript code to your website and handle the height in Javascript.

It still does not work for me!

First of, try adding borders to see the edges of your boxes.

Second, verify all your paddings and margins. In most cases, you should define a padding: 0px; and margin: 0px; for the DIV element to avoid all interferences.

If a top container or wrapper includes a padding or margin, the 100% may not represent the width of the screen but instead the width of the screen minus that padding or margin. Make sure you do not include that size in your computations.

Finally, are you using Internet Explorer? It is a quite broken browser and you are not unlikely to need some special tricks to handle that one.

  • 1. This means you could create 3 columns of 20%, 60% and 20% and be done with it. The problem with that method is that the left and right bars will be resized and often that is not what you want. And they cannot have a minimum width independent from the rest.