How to make a stable two column layout in HTML/CSS

Triynko picture Triynko · Apr 7, 2011 · Viewed 123.8k times · Source

I want a container with two columns. Details:

The container

  • Width should adjust to 100% of its parent element (easily accomplished).
  • Height must adjust to contain both columns (i.e. its height should be exactly equal to the larger height of the two columns, so there is no overflow and scrollbars never show)
  • Should have a minimum size equal to double the width of the left column.

The columns in general

  • Should be of variable height, adjusting to the height of their content.
  • Should be side-by-side, such that their top edges are in line.
  • Should not break the layout or wrap under each other if even a single pixel of border, padding, or margin is applied to either one, because that would be extremely unstable and unfortunate.

The left column specifically

  • Must have a fixed, absolute width in pixel units.

The right column specifically

  • Width must fill the remaining space in the container. In other words...
  • Width must equal the container width minus the width of the left column, such that if I place a DIV block element inside this column, set its width to 100%, give it a height of something like 10px, and give it a background color, I will see a 10px high colored strip that goes from the right edge of the left column to the right edge of the container (i.e. it fills the right column's width).

Required stability

The container should be able to resize (by resizing the browser window) down to its minimum width (specified earlier) or to a much larger width without breaking the layout. "Breaking" would include the left column changing size at all (remember it's supposed to have a fixed pixel width), the right column wrapping under the left one, scrollbars appearing, block elements in the right column failing to take up the entire column width, and in general any of the aforementioned specifications failing to remain true.

Background

If floating elements are used, there should be no chance that the right column will wrap under the left one, that the container will fail to contain both columns (by clipping any part of the column or allowing any part of the columns to overflow its boundary), or that scrollbars will appear (so I'd be weary of suggesting the use of anything other than overflow:hidden to trigger floating-element containment). Applying borders to the columns should not break the layout. The content of the columns, especially of the right column, should not break the layout.

There seems to be a simple table-based solution to this, but under every circumstance it fails miserably. For example, in Safari, my fixed-width left column will shrink if the container gets too small, rather than maintaining the width I specified. It also seems to be the case that CSS width, when applied to a TD element refers to a minimum width, such that if something larger is placed inside it, it will expand. I've tried using table-layout:fixed; doesn't help. I've also seen the case where the TD element representing the right column will not expand to fill the remaining area, or it will appear to (for example a third column 1px wide will be pushed all the way to the right side), but putting a border around the right column will show that it's only as wide as its inline content, and block-level elements with their width set to 100% do not fill the width of the column, but rather match the width of the inline-content (i.e. the width of the TD seems to be completely dependent on the content).

One potential solution I have seen is too complex; I couldn't care less about IE6, as long as it works in IE8, Firefox 4, and Safari 5.

Answer

richzilla picture richzilla · Apr 7, 2011

Here you go:

<html>
<head>
  <title>Cols</title>
  <style>
    #left {
      width: 200px;
      float: left;
    }
    #right {
      margin-left: 200px;
      /* Change this to whatever the width of your left column is*/
    }
    .clear {
      clear: both;
    }
  </style>
</head>

<body>
  <div id="container">
    <div id="left">
      Hello
    </div>
    <div id="right">
      <div style="background-color: red; height: 10px;">Hello</div>
    </div>
    <div class="clear"></div>
  </div>
</body>

</html>

See it in action here: http://jsfiddle.net/FVLMX/