Equal Height Column Layouts with Borders and Negative Margins in CSS

Advertisement

“What? Another “Equal Height Columns” article? Enough already!” If this is what you think, then think again because this solution is different. It does not rely on any of the usual tricks. It does not use images, nor extra markup, nor CSS3, nor pseudo-classes, nor Javascript, nor absolute positioning. All it uses is border and negative margin. Please note that this article will also demonstrate different construct techniques and will brush up on a few concepts.

1. Centering columns without a wrapper div

This layout will be built without a wrapper div:

Two column layout

The basics

We use the background of body and the border of one of the columns to create background colors that vertically fill the “row”.

The markup

<div id="header">
	<h2><a href="#">Header</a></h2>
	<p>Lorem ipsum...</p>
</div>

<div id="sidebar">
	<h2><a href="#">Sidebar</a></h2>
	<p>Lorem ipsum...</p>
</div>

<div id="main">
	<h2><a href="#">Main</a></h2>
	<p>Lorem ipsum...</p>
</div>

<div id="footer">
	<h2><a href="#">Footer</a></h2>
	<p>Lorem ipsum...</p>
</div>

Tip: always include links within your dummy text to spot stacking context issues.

About using body as a wrapper:

  • always style html with a background to prevent the background of body from extending beyond its boundaries and be painted across the viewport.
  • never style html with height: 100% or the background of body will be painted no taller than the viewport.

The CSS

html {
  background: #9c9965;
}

body {
  width: 80%;
  margin: 20px auto;
  background: #ffe3a6;
}

#header {
  background: #9c9965;
}

#sidebar {
  float: left;
  width: 200px;
  background: #d4c37b;
}

#main {
  border-left: 200px solid #d4c37b;
}

#footer {
  clear: left;
  background: #9c9965;
}

What do these rules do exactly?

  • We style html with a background to prevent the browser from painting the background color of body outside our layout.
  • We style body with auto margin to center the layout; the width is set using percentage. The background declaration is for #main.
  • We style the background of #header to mask the background color of body (the same goes for #footer).
  • The background color of #sidebar matches the border color of #main. This is the trick we use to make our columns appear as being of equal height.
  • The footer clears any previous float so it stays below the columns, at the bottom of the layout.

If you take a look at this first step, you’ll notice that the heading in #sidebar is not vertically aligned with the heading in #main and that we have some gap at the top and bottom of the #sidebar. This is because out of these two containers, only one is a block formatting context. So margins do not collapse in #sidebar while they do in #main. This also means that #main will not contain floats and that applying clear:left to any nested element in there will clear #sidebar as well.

So to prevent any float and margin collapsing issues we make all the main boxes block formatting contexts.

#header,
#footer {
  overflow: hidden;
  zoom: 1;
}

#main {
  float: left;
}

#sidebar {
  margin-right: -200px;
}

Note: if things look a bit different in IE 6 and 7 it is because in these browsers default margins do collapse inside block-formatting contexts. The following should also be considered:

  • overflow and zoom on #header and #footer make these elements new block formatting contexts.
  • For #main we use float rather than overflow to prevent potential issues if we had to offset some nested content.
  • The negative margin keeps #main into place because now that it is a float, its border box comes next to the margin box of #sidebar (the negative vlaue must match the dimension of the said box).

If you look at the second step, you’ll see that the border of #main hides #sidebar. This is because of the stacking context. In the flow (tree order), #main comes after #sidebar so the former overlaps the latter.

Positioning #sidebar brings it up in the stack.

#sidebar {
  position: relative;
}

Note: if you make #main a new containing block you’ll revert to the original stack order. In this case, you’ll need to use z-index to keep #sidebar on top of #main.

If you look at step three, you’ll see that we are almost there. The last things to do are mostly cosmetic. I’ve inserted a base styles sheet:

<link rel="stylesheet" type="text/css" href="http://tjkdesign.com/ez-css/css/base.css">

and then added these rules:

html {
  height: auto;
}

body {
  border: 1px solid #efefef;
}

#header,
#main,
#sidebar,
#footer {
  padding-bottom: 2em;
}

Why do we need these rules?

  • We can reset the height on html so the background of #main is not cut-off at the fold (this styling is inherited from the base styles sheet).
  • We can draw a border all around the layout.
  • Because the base styles sheet only sets top margins, we can create gaps at the bottom of the main boxes via padding.

Note: The rule for html is shown here, but it makes more sense to remove that rule from the base styles sheet rather than overwriting the declaration here.

This is the last step for this first layout. It relies on these simple rules:

html {
  height: auto;
  background: #45473f;
}

body {
  width: 80%;
  margin: 20px auto;
  background: #ffe3a6;
  border: 1px solid #efefef;
}

#sidebar {
  float: left;
  position: relative;
  width: 200px;
  margin-right: -200px;
  background: #d4c37b; /* color must match #main's left border */
}

#main {
  float: left;
  border-left: 200px solid #d4c37b; /* color must match #sidebar's background */
}

#header,
#footer {
  clear: left;
  overflow: hidden;
  zoom: 1;
  background: #9c9965;
}

#header,
#main,
#sidebar,
#footer {
  padding-bottom:2em;
}

2. Creating a 2-col-layout with two borders in between the columns

We’ll build this one with a single wrapper for our two columns, and we want to paint a vertical border between the two columns.

Two column layout with two vertical borders

The basics

The wrapper div allows us to be a bit more creative here. The background of the wrapper is used to paint the background of one column, while its left border is used to paint the background color of the other column. The vertical border will be done by overlapping the right border of the left column with the left border of the right column.

Note: if you have use a fixed width layout (vs. fluid like here), then the wrapper can be used to create the two background colors as well as the vertical border at the same time. This is done by using the left border for the left column, the right border for the right column and the background for the vertical border. Yes, this means the content box is one pixel wide and that negative margins are used to pull the columns into place.

Markup

<div id="header">
	<h2><a href="#">Header</a></h2>
	<p>Lorem ipsum...</p>
</div>

<div id="wrapper">
  <div id="sidebar">
  	<h2><a href="#">Sidebar</a></h2>
  	<p>Lorem ipsum...</p>
  </div>
  <div id="main">
  	<h2><a href="#">Main</a></h2>
  	<p>Lorem ipsum...</p>
  </div>
</div>

<div id="footer">
	<h2><a href="#">Footer</a></h2>
	<p>Lorem ipsum...</p>
</div>

CSS

We start with the generic rules from the previous demo:

html {
  background: #45473f;
}

body {
  width: 80%;
  margin: 20px auto;
  background: #ffe3a6;
}

#header,
#footer {
  overflow: hidden;
  zoom: 1;
  background: #9c9965;
}

#sidebar {
  float: left;
  width: 200px;
}

#main {
  float: left;
}

To which we add position: relative:

#wrapper {
  display: inline-block;
  border-left: 200px solid #d4c37b;
  position: relative;
}

#sidebar {
  margin-left: -200px;
  position: relative;
}

Note: there is no need to use clear on the footer since #wrapper contains both floats.

  • Rather than using overflow/zoom, we use inline-block to create a new block formatting context (this declaration also triggers hasLayout). The left border will paint a background color behind #sidebar.
  • Negative margin is used to bring #sidebar outside the content box of the parent’s container (to make it overlap the border of #wrapper).

The case of IE6: If the above rules use position: relative (twice), it is because of IE 6. It is applied on #wrapper to prevent #sidebar from being clipped outside of its content box. It is also applied on #sidebar to make sure that the elements are “always” painted with the proper offset.

If you look at this first step, you’ll see that we have everything working, but the vertical border is in between the columns. You should also notice that in browsers other than IE 6 and 7, there is a small gap at the bottom of #sidebar (at the bottom #wrapper actually). This is because #wrapper is styled with inline-block so it is sitting on the baseline of the line box. The gap you see is the “descender space” (the space reserved for descenders in lowercase letters).

So these are the rules to remove the gap and create the vertical border:

#wrapper {
  vertical-align: bottom;
}

#sidebar {
  margin-right: -1px;
  border-right: 1px solid #888;
}

#main {
  border-left:1px solid #888;
}

What do these rules do?

  • vertical-align: bottom makes #wrapper sit at the bottom of the line box rather than the baseline.
  • the two borders (for #sidebar and #main) overlap because of the negative right margin set on #sidebar. This overlap guarantees that this “common” border will be as tall as the tallest column.

If you look at step two, things look much better. The last things to do is to add the base styles sheet and the same rules we used at the end of the first demo:

<link rel="stylesheet" type="text/css" href="http://tjkdesign.com/ez-css/css/base.css">

and then add these rules:

html {
  height: auto;
}

body {
  border: 1px solid #efefef;
}

#header,
#main,
#sidebar,
#footer {
  padding-bottom: 2em;
}

This last demo for this layout includes the above rules.

3. Creating a three column layout with a border in between the columns

We’ll build a layout with a single #main-wrapper, one containing all the divs. This approach complicates things a bit, but it also allows to tackle new challenges. Please note that with this layout, the vertical borders will not show in IE 6 and 7.

Three column layout with vertical borders

The basics

We use the wrapper to create the background of the three columns. The left and right borders of the wrapper will be used for the two side bars while its background will be used for the main content.

The markup

<div id="wrapper">
  <div id="header"><h2><a href="#">Header</a></h2><p>Lorem ipsum...</p></div>
  <div id="sidebar"><h2><a href="#">Sidebar</a></h2><p>Lorem ipsum...</p></div>
  <div id="aside"><h2><a href="#">Aside</a></h2><p>Lorem ipsum...</p></div>
  <div id="main"><h2><a href="#">Main</a></h2><p>Lorem ipsum...</p></div>
  <div id="footer"><h2><a href="#">Footer </a></h2><p>Lorem ipsum...</p></div>
</div>

CSS

We start with the generic rules from the previous demos:

html {
  background: #45473f;
}

body {
  width: 80%;
  margin: 20px auto;
  background: #ffe3a6;
}

#header,
#footer {
  overflow: hidden;
  zoom: 1;
  background: #9c9965;
}

#sidebar {
  float: left;
  width: 200px;
}

#main {
  float: left;
}

To which we add:

#wrapper {
  border-left: 200px solid #D4C37B;
  background-color: #ffe3a6;
  border-right: 200px solid #D4C37B;
}

This code sets the background color for the three columns. In the same sequence as the above declarations.

If you look at this first step, you’ll see that we have achieved the background effect we are looking for, but things look pretty broken. Everything shows inside the wrapper’s content box.

These next rules should fix the display of the three columns (zoom: 1 for the #wrapper and position: relative for #sidebar and #aside):

#wrapper {
  zoom: 1;
}

#sidebar {
  margin-left:-200px;
  position: relative;
}

#aside {
  float: right;
  width: 200px;
  margin-right: -200px;
  position: relative;
}

#aside is given a width and floated to the right. The negative margins pull each side bar over the wrapper’s border — outside of the content box.

Note:IE 6 and 7 needs #wrapper to have a layout, hence the use of zoom. IE 6 needs the two position declarations for the same reason as in the previous demos.

If you look at step two, you’ll see that #header does not stretch across the entire layout and that #footer is nowhere to be found.

These two rules should take care of everything:

#header,
#footer {
	margin-left: -200px;
	margin-right: -200px;
	position: relative;
}

#footer {
  clear: both;
}

The negative margin on both sides of #header and #footer stretches the two boxes outside of the wrapper’s content box. clear:both makes the footer clears all the columns. This is step three.

Once again, the position declaration is for IE 6. Just remember to always position elements that you offset.

What’s next?

You know the drill. We insert a base styles sheet in the document:

<link rel="stylesheet" type="text/css" href="http://tjkdesign.com/ez-css/css/base.css">

and add the usual:

html {
  height: auto;
}

body {
  border: 1px solid #efefef;
}

#header,
#main,
#sidebar,
#footer {
  padding-bottom: 2em;
}

Step four shows how things look before we tackle the vertical borders.

Adding vertical borders

The following technique is inspired from the companion columns technique (Ingo Chao) and the Nicolas Gallagher method.

To get the effect we want (two borders touching each other), we use generated content to which we apply a background color and a border.

The CSS

html:before {
	content: ".";
	position: absolute;
	height: 20px;
	background: #45473f;
	left: 0;
	right: 0;
	z-index: 2;
}

body {
  border-top: 0;
}

#header {
  border-top: 1px solid #fff;
}

#wrapper {
  position: relative;
}

#header,
#footer {
  z-index: 1;
}

#wrapper:before,
#wrapper:after {
  content: ".";
  position: absolute;
  width: 1px;
  height: 2000px;
  background: #9c9965;
  bottom: 0;
}

#wrapper:before {
  left: 0;
  border-left: 1px solid #fff;
}

#wrapper:after {
  right: 0;
  border-right: 1px solid #fff;
}

body {
	position: relative9;
	z-index: -1;
}

OK, so what’s going on here?

  • The fake borders get out of the container (at the top), so the first rule paints generated content on top of them. Note that we would not need this rule if the color of the fake borders was the same as the page’s background (html), or if there was no gap between the top of the viewport and the layout.
  • Because these borders are painted over the border around body, we move the top border from body to #header.
  • To properly position the fake borders, we need to make the wrapper the containing block for the generated content.
  • We bring #header and #footer above the stack so they hide the fake borders which are painted inside the wrapper (from bottom to top).
  • This is the generated content we use to create the columns.

The case of IE 8: The last rule is for IE 8. Without this, IE 8 would not paint the generated content over the borders that escape the wrapper (at the top). If this declaration is sandboxed via the “9″ hack, it is because Gecko browsers would make everything unclickable/unselectable.

Note: these pseudo-classes are not supported by IE 6 and 7, so in these browsers, there are no borders between the columns.

Things to consider

The third layout uses one main wrapper, but it would make more sense to use a inner wrapper instead to hold only the columns. In case this route was taken here, then it was only for those of you who are stuck with this type of construct, but want to implement this solution for equal height columns.

When absolutely positioning elements inside a containing block with wide columns like in the last two demos, remember that the reference is the padding box, so 0 for right or left may not be the value you would want to use.

Further reading

(ik) (vf)

↑ Back to top

Thierry is passionate about Web Design and CSS. He loves the challenge of solving problems and dreaming up original ideas that get him out of bed in the morning and keep him working late at night. He is a front-end engineer at Yahoo! and owns TJK Design, css-101.org and ez-css.org. His twitter handle is @thierrykoblentz.

  1. 1

    Jeremiah Sherrill

    November 8, 2010 7:40 am

    What no 6 column layout? I am disappointed in all of you. ;-)

    4
  2. 2

    To get equal height columns, it’s easy if you use display: table and display: table-cell properties and values. There’s a lot less CSS involved. Works in IE8+ and other modern browsers. Not so good for IE6 and 7 but I think it’s worth considering.

    -25
  3. 3

    What, no HTML5? For shame.

    -35
  4. 4

    I’m not sure I understand the practicality of this. What advantages does it have over something like 3 columns made up of floated block elements with a repeating 1px high background image? More flexibility if the column widths change?

    I don’t like putting things like negative margins or 200px borders in my code because it feels like a hack. There are also lightweight jquery solutions like the matchHeights plugin that finds the column that is the tallest, and adjusts the others to match the height using normal css.

    2
  5. 5

    Nice article, and well written. I particularly enjoyed the idea of leaving out the wrapper div, a step I always feel is extraneous. It’s always good to see CSS used in intuitive ways to simplify our efforts on the web, it’s nice to think there’s more and more potential still left in the language.

    -2
  6. 6

    Or you can use a (html) table of two or three columns. And… it’s done. :)

    -36
  7. 7

    Perhaps this link can contribute this article.

    http://www.code-sucks.com/css%20layouts

    -4
  8. 8

    interesting idea to use the body as the wrapper. i’ve never thought of that before actually. is that a standard practice does anybody know?

    0
  9. 9

    Why not use a simple table?

    -24
  10. 10

    Thanks for mentioning in the beginning of this article
    “It does not rely on any of the usual tricks. It does not use images, nor extra markup, nor CSS3, nor pseudo-classes, nor Javascript, nor absolute positioning. ”

    So i like this post no matter how many other solutions are available.

    2
  11. 11

    Because of the coders revenge: If you are no a good graphic designer, make it hard for the no-coders.
    Soooooooooo sad.

    -14
  12. 12

    It doen’s work if you want a more complicated background on your website that uses both the en tag. But for simple lay-outs, it’s a nice trick! Well found!

    -1
  13. 13

    nice article…like the idea of using the body as the wrapper. I did something just like this, but used a left margin instead of the border…works on all browsers. YUI has some good stuff on this also.

    1
  14. 14

    I can’t believe I haven’t thought of this before. I’ll definitely be using this method; thank you =)

    -1
  15. 15

    Finally a good practical article like in the good ol’ time

    -2
  16. 16

    Nice article… that is, for those stuck with html4.
    Sorry but it seems to me that every div-less layout purist here is contradicting the point of staying away from tables for design. They said that its not semantic to use a tables for layout and web developers needed to stick with tables years ago because they had limited set of tools to work with.
    But now that there is html5 and css3, why not take advantage earlier of what power it offers? I mean come on, SM already posted a while ago articles with Interesting Navigation Designs, and almost (if not, then all) featured uses JavaScript, CSS3 and HTML5. Don’t you think column-layouts are outdated already?
    Point is, instead of wasting time to create an article of this high-quality that will only be useful for a short time, why not just teach designers how to create those layouts featured with Interesting Navigation? Wouldn’t that be more useful?

    -3
  17. 17

    good article but using jQuery is sooooo much easier. It’s cross browser without using any extra hacks too.

    -2
  18. 18

    Good article thank you very much, i need to learn web design how to?

    -4
  19. 19

    What advantages does it have over something like 3 columns made up of floated block elements with a repeating 1px high background image?

    You’d not need one, but two images as these layouts are fluid (unless you use extra markup). These would be extra HTTP requests and color changes would be more complicated to maintain.

    There are also lightweight jquery solutions like the matchHeights plugin that finds the column that is the tallest, and adjusts the others to match the height using normal css.

    I don’t think we should be using Javascript to style our documents. Besides, this would be pretty bad regarding CPU as the script would have to calculate new values each time the user resize the window as the content would vertically shrink or grow inside the “fluid” column.

    -2
  20. 20

    Nice Article , But I would Use a background Image and repeat it for Wrapper Instead for Border, The size of the image will be less then 1 KB

    0
  21. 21

    Nice Article…and very well explained….

    -1
  22. 22

    Thanks Thierry. I’ve been trying to find a good solution for equal height columns for awhile. Never cared for faux columns or most of the other solutions I’ve seen. Borders and negative margins. Seems so obvious now that you’ve shown the solution.

    Appreciate the effort figuring this out as well as the post explaining how it’s done.

    -1
  23. 23

    I tried this solution several years ago, but when I want to change the sidebar background with a image, this solution is not good enough.

    -1
  24. 24

    So… Tables are dismissed because of the (Pavlov) reaction that ” tables are for tabular data” ( which I agree with) but you think it’s okay to use a border like this?

    I think this is a very bad article, focusing on a trick, while the focus should be on having an understandable, maintainable and locical layout. The trick is nice and helps people understand css and it’s possibilities but it should have been placed in an appropriate context instead of being presented as a real and usable solution.

    2
  25. 25

    Wow, who remembers Stu Nicholls then! It’s been quite a while since I heard about this technique, not too big a fan because of all its limitations though.

    -1
  26. 26

    Nice trick :)
    And what about extending it with css3 border-image? Maybe it could provide some interesting possibilities for experimentalists.

    Just an idea – haven’t thought of it in great depth.

    0
  27. 27

    This is a great technique if you don’t mind bland designs and don’t use images in your designs. Which modern design can allow plain border-color to make its aside? But it is so much better for speed! Yeah, leaving the .CSS out of the design entirely (wouldn’t notice with a bland design) saves another http request!

    Faux-Column technique has nothing on this border hack. But the extra request! That request is already there for the mega-sprite, that fills all image backgrounds. Adding a few kb to that request you won’t notice, and bonus: You can make a website look like it was designed with gradients and shadows, instead of a couple of opaque blocks that try to mimic 1996 table designs.

    For all the standards adhering freaks out there, being the first to tell us you shouldn’t use tables for anything but tabular data, not even use it for arranging data, as the spec allows, shouldn’t you cry faul about the big ZOOM: 1 statement?

    Seriously? I think an ugly hack isn’t complete without some browser-vendor specific code to make it work…

    -1
  28. 28

    Great way to use CSS in a clever way, thanks a lot man!

    -1
  29. 29

    Well done Thierry,love what you did , especially in not using images or css3 or the like. It sort of reminds me of an article found in this site:
    http://camendesign.com/code/developpeurs_sans_frontieres
    It states that the body can be treated as a wrapper and given all the usual attributes. I also like the idea of less http requests.

    Once again well done!

    0
  30. 30

    Amazing post, Thierry. I wish I had this a few days ago when I was coding a site that required very touchy column equalisation – had to resort you using javascript.

    This feels like a very clean and ‘hack free’ method, great work :D

    -1
  31. 31

    “Do more with less” is the best CSS solution…

    Great article…

    0
  32. 32

    Well the thing is, these “equal columns” aren’t really equal. They just looks like equal, but they are not. It’s ok to use this solution on simple websites, but when you have complex layout, this method is pretty useless.

    0
  33. 33

    Is it possible to use this markup with the ‘FooterStickAlt’ solution?

    0
  34. 34

    Good article, code works great in firefox and chrome

    0
  35. 35

    LOL @ table trolls!

    3
  36. 36

    This method i find to be buggy in older browsers. I go with the good old theory on this one “If it isn’t broke, Don’t try to fix it”. Yes we need to look at new ways to do things but i think this one should be put back on the shelf & stored away.

    Time matters & this takes a lot longer.

    Just my humble opinion :)

    0
  37. 37

    The problem that I have with this is source ordering. The content in the left column is generally less important than that in the center column and those using screen readers (if not given the proper tools) now have to scroll through a lot more useless stuff.

    1
  38. 38

    It seems like this method would work well for sites under a huge traffic strain, or sites for people on something like a 56k dial-up connection, but it might be too minimalist for most brochure sites, e-commerce sites, or websites with moderate to highly detailed designs.

    To the Table-ists: Aesthetically div tags are the modern and preferred way to set up a page and it is possible to set up a website using tables, it’s not always a good idea. But really it’s possible to take any tag and use it as a layout element. You could make the 3 columns a huge list with each column being an li tag. As long as it validates and looks consistent cross-browser it’s ok. I’m not suggesting that people start making pages out of p tags, I’m just saying that this holier-than-thou tables v. divs back and forth is ridiculous. Everyone should just make their pages the way they make their pages, and stop criticizing each other like children saying that other methods are blasphemy.

    Ideally we’re here to learn and help each other instead there’s a lot of comments with this elitist “my way is better than anyone else’s” attitude, and there’s no reason for it. Thierry, thank you for sharing this method with us.

    2
  39. 39

    This sucks. Thumps down.

    2
  40. 40

    is there a download link as opposed to copy and paste?

    0
  41. 41

    Nice article, very useful!

    -1
  42. 42

    Another point against the table-boosters: if your site depends on dynamic content, it’s much, much easier to Make Things Work with ad hoc layouts if you don’t have to worry about managing cells in a table. And if you’re actually competent at both techniques, you’ll find that table-less layouts dramatically reduce your bandwidth and storage consumption to boot.

    And count me among the head-slappers who say, “I should have thought of that!” The whole point of a wrapper div is to get everything inside a nice, big block-oriented tag. Well, last I checked, ‘body’ isn’t an inline tag at all…. ;-)

    1
  43. 43

    If i remember correctly i previously used a method with a column container inside my wrapper.

    #wrapper {
    Min-height:595px;
    width:700px;
    etc…
    }

    #columnContainer
    {
    overflow:hidden;
    }

    And then my two columns would have something like:

    {
    float:left;
    width:200px;
    min-height:500px;
    padding-bottom: 20000px; /* X + padding-bottom */
    margin-bottom: -20000px; /* X */
    background: url(../what-ever-jpg) repeat-y;
    }

    Worked like a charm, but obviously you need an extra “wrapper” div and the figure 20000 needs to be set manually for longer sites/pages

    -1
  44. 44

    Hello,

    Nice article……………………….. u can find more discussions on cutting edge techs on tahSin’s garAge

    0
  45. 45
  46. 46

    Hi Thierry,

    Nice article and well written as usual.

    I like the generated borders method but you don’t need those extra hacks for IE8 and you don’t need the extra html element on html to cover it up. Just use top and bottom for the absolute element and it will be contained within the wrapper at whatever height it happens to be so you don’t need the height declaration either.

    e.g.

    #wrapper:before,
    #wrapper:after {
    content:” “;
    position:absolute;
    width:1px;
    background:#9c9965;
    bottom:0;
    top:0;
    }

    It’s basically the same method I’ve been using for my absolute column overlays for years and works very well but I do like your use of generated content to produce the borders although it does cut IE7 out of the game unlike the extra mark up method.

    I do have qualms about using the body element as a wrapper though as it throws the zoom right out in IE7 (and can play havoc with IE6 unless you set position:relative on the body also (It breaks completely in IE5 but thankfully we don’t need to worry abut that these days)). For the sake of one extra wrapper I just don’t think it’s worth the effort (see mine and Tommy’s comments here http://blogs.sitepoint.com/2009/02/11/styling-the-html-and-body-elements/ )

    A minor point but I though it also might be in order to give a “hat-tip” to the original author of this border column method as his name seems to be missing from the above links. The negative margins and thick column border method was first devised by Doug Livingstone (http://redmelon.net/tstme/3cols2/) way back in 2002/3 (and a similar method then adapted by me inspired by Doug also back in 2003) pre-dating all the rest by many many years.

    Good article though and well explained.

    0
  47. 47

    I am fresher but articly was good to understand. Thank You !

    0
  48. 48

    Really amazing blog. I really appreciate your work. Thanks

    0
  49. 49

    Just a comment about CSS.
    I work in this agency where they don’t care about css, or webstandards, my boss even asked today to make a website with tables rather than with “styles” because “old school web” is much better. I just feel really frustrated right now… Any comments?

    0
  50. 50

    very informative thanks for sharing

    0
  51. 51

    Love this solution. This is solid compare to earlier versions.
    Just a suggestion, Is there any problem if we use styling of a div container on place of body?
    Current CSS:

    html {
    background:#45473f;
    }
    body {
    width:80%;
    margin:20px auto;
    background:#ffe3a6;
    }

    Modified:

    body {
    background:#45473f;
    }
    #anydiv{ /* This div will come outside of all div, inside body*/
    width:80%;
    margin:20px auto;
    background:#ffe3a6;
    }

    i have tried this and it is working fine. This is also help full in case of complex html where you need body tag for other styles.

    Regards,
    Sachin kumar
    sacmonk.com

    0
  52. 52

    Another solution that may be of interest which works in Safari, Chrome, Firefox and IE right back to IE6: http://thelucid.com/2010/12/03/the-solution-to-fluid-inconsistencies-and-equal-height-columns/

    0
  53. 53

    am new to div based web design, till now used table based design, it is cool and easy to understand.. thanks

    0
  54. 54

    > Tip: always include links within your dummy text to spot stacking context issues.

    Could you please elaborate on this?

    0
  55. 55

    @Thierry Koblentz

    Do you have an example for the last example with the borders?
    without this its, useless for me…

    0
  56. 56

    Yep. I also would recommend the display:table -options.

    -28
  57. 57

    Well, that only leaves out 25% of internet users. I’m sure my clients will jump at that.

    3
  58. 58
  59. 59

    thats what I was going to say, why not just use a table?

    -36
  60. 60

    Consider your skills before commenting.

    -8
  61. 61

    Because tables are for tabular data. Not layout.

    21
  62. 62

    but I don’t get it, you are using CSS to imitate a table. Why not just use a table?

    -33
  63. 63

    @Tim,

    But also css in their current state were never intended to be for layout (except for cases where all the widths and heights are fixed). Float was a tool made to allow the text to float around an image or another block of text, not for layout.

    So among both tools, I prefer the most practical one : tables.

    And, one point. Tables are for the layout of tabular data. So, if they can organize the layout of tabular data, they can also organize the one of non tabular data. What I mean is that, concerning layout and presentation, tables don’t come from outer space. They already have this purpose in the realm of tabular data. So, you just extend this purpose to some non tabular uses (mostly the 2 or 3 columns problem). CSS, however, where never intended to be used for non (width and height) fixed layout. So, the tool which had, at the begining, the most the goal of being for layout is : tables.

    -14
  64. 64

    Tim said it best: “Because tables are for tabular data. Not layout.”

    Long ago we used tables because we couldn’t do any better. We had a limited set of tools to work with. We didn’t have the CSS tools for _display_ that we have today. CSS is for display, tables are for data.

    Also, the last time I used a table for layout, a masked man ran by and kicked me in the nuts. I am still afraid of layout tables to this day. Don’t let this happen to you!

    17
  65. 65

    It is about semantics. You use tables for tabular data, giving it semantic purpose. There’s nothing semantic about a table layout.

    5
  66. 66

    There’s also speed and maintenance issues to consider.

    A page laid out with tables will load considerably slower than a page laid out with divs (even if they are set to “display: table”).

    Also, if you decide to change anything major in your layout, it will be very difficult to make the changes. A layout with positioned/floated divs is much easier to maintain and/or alter.

    Take it from someone who coded and maintained table-based layouts in the dark ages for a good 7+ years! :)

    6
  67. 67

    @Gerald do you really know what is HTML Table and CSS really means? Funny to say -> “CSS to imitate a table”.

    -12
  68. 68

    @Justin,

    You can put 3 divs in a 3 columns table. And you have the best of both worlds : the semantic and the comfort and simplicity of tables.

    -14
  69. 69

    @Louis,

    About the loading speed, it was true when there was designs with tons of nested tables. This is no more the case. We are talking about 2 or 3 columns layouts. There won’t be any difference of speed between the two techniques in this case.

    And about maintenance issue, the solution is simple : templates. And it’s more powerful than css. Because with css only, if you want to add another column to your layout, you can’t. With a template system, you can.

    And of course, with templates, you can do every other things that css do.

    -5
  70. 70

    I agree with Tim and also bmfv is right. Tables are for tabular data, not for layout. It is useful before inventing CSS, because tables have more attributes, have child elements and they can control the vision of the content ( means that two columns or how much it is ) than other HTML elements at that time. Today, tables are outdated for layout formatting.

    0
  71. 71

    @Francois
    “About the loading speed, it was true when there was designs with tons of nested tables. This is no more the case. We are talking about 2 or 3 columns layouts. There won’t be any difference of speed between the two techniques in this case.”

    You’re wrong.
    Browsers STARTS displaying tables AFTER they read ALL table. SO layout in table will start displaying after whole pahe is loaded. Imagine whath it looks like when you have very long arcicles on a page?

    0
  72. 72

    This is a CSS article not an HTML article :)

    Very nice and informative article Thierry.

    16
  73. 73

    The CSS rules target IDs, not HTML elements, so one can use the same sheet with HTML5 as well.

    1
  74. 74

    Table-tag is for showing data in a table or lists, e.g. pricelists

    -2
  75. 75

    oh my, you should re-read all the comment before.

    -3
  76. 76

    The advantage it has is that it uses no images and no Javascript/jQuery at all.

    1
  77. 77

    It might feel like a hack. It isn’t.

    If we had to put the + symbol in front of padding/margin sizes, then it wouldn’t even cross our minds that using negative margins/padding is “dirty dirty dirty.”

    0
  78. 78

    Faux columns is as much of a hack as this method.

    But I have to agree with John in that I rarely have to do layouts that just deal with solid background-colors and borders; there’s always gradients or shadows or something else added which means I’d rarely ever use this technique.

    5
  79. 79

    In a real world scenario it is rare to have two columns that are solid colors and can be easily re-created using a massive border. It’s a great solution if the page needs to be self-contained with no dependencies and solid color backgrounds, and a clever way to create equal heights.

    That being said I’m still having trouble finding a practical application as I’ve never seen a commercial design where everything had a solid color behind it. If a repeating background image is used in place of the solid border color it’s still going to expand the height according to the tallest column (assuming the float is cleared properly), so the advantage of this method is lost and it ends up being much more css than is needed to achieve the same result.

    4
  80. 80

    Hi Gabri,
    Thanks for your feedback!

    2
  81. 81

    If a repeating background image is used in place of the solid border color it’s still going to expand the height according to the tallest column (assuming the float is cleared properly), so the advantage of this method is lost and it ends up being much more css than is needed to achieve the same result.

    HTTP requests are expensive, and there is also the initial download time of the image.

    0
  82. 82

    But I have to agree with John in that I rarely have to do layouts that just deal with solid background-colors and borders.

    I’d say that for large sites it makes a lot of sense in term of download time, HTTP requests, image maintenance, etc.

    For example, these are two sites using columns with a solid background color:

    http://www.twitter.com
    http://finance.yahoo.com/news

    Thanks for your feedback

    -2
  83. 83

    Hi Bobby,

    If you give body a try (as a wrapper), make sure to read my “warnings” at the beginning of the article (re: background and height).

    Thanks for your feedback.

    -2
  84. 84

    Hi Erik,

    I would not call this “standard practice”, but I’ve used it a few times without problem.
    One thing though, authors should style body with a min-width as they would with a div wrapper. Something I did not mention in this article.

    Thanks for your feedback

    0
  85. 85

    good article but using jQuery is sooooo much easier. It’s cross browser without using any extra hacks too

    Using Javascript to style and resize your columns is a hack. And as I mentioned earlier, such approach is pretty bad in term of performance (CPU).

    Thanks for your feedback

    -3
  86. 86

    Thanks SIA

    -1
  87. 87

    Thanks for the kind words

    -2
  88. 88

    I would Use a background Image and repeat it for Wrapper Instead for Border, The size of the image will be less then 1 KB

    There is more to it than the weight of the image. Consider these:
    - the HTTP request,
    - the initial download time,
    - the maintenance related to the image (a new image has to be created and pushed each time the background color needs to be changed),
    - the look of the page with images off,
    - etc.

    Thanks for your feedback

    -1
  89. 89

    Hi Steven,
    Thanks for the kind words

    0
  90. 90

    I am not aware that Stu Nicholls demonstrates this technique on his web site.
    I know about these layouts [1], but I believe they all rely on background color and extra markup.
    Could you please post a URL?
    I’d really appreciate.
    Thanks

    [1] http://www.cssplay.co.uk/layouts/three-column-layouts.html

    -1
  91. 91

    We are all here to learn.. Consider respecting (and helping) the once just starting with css ;)

    9
  92. 92

    if my skills are incorrect, should I continue to be incorrect? or should I comment here and learn something?

    5
  93. 93

    Richard,

    The trick is nice and helps people understand css and it’s possibilities but it should have been placed in an appropriate context instead of being presented as a real and usable solution

    I use this “trick” on a very high traffic web site, so I think I can say it is a real and usable solution.
    It saves us a HTTP request, it saves us the initial download, it makes the page look good with images off, it saves us from dealing with an extra asset, etc.

    Thanks for your feedback

    -1
  94. 94

    Hey Thierry,

    you can find Stu’s trickery over here: http://www.cssplay.co.uk/layouts/threecol.html
    The link on that page refers to an example of a column layout using borders.
    Direct link: http://www.cssplay.co.uk/layouts/3cols.html

    Just for the record, this is not a “you stole it” type of comment, this post here just reminded me of Stu and his somewhat unusable site filled with really ingenious css tricks. When I was investigating several column layouts a couple of years ago I stumbled upon Stu’s method (he’s always thinking outside the box it seems).

    -1
  95. 95

    Twitter use two column, but I don’t understand how it works!!!

    Witch method does they use ?

    Thanks.

    -3
  96. 96

    @Thierry That’s a great point, and it would be great for sites with very high traffic, and I’ll definitely keep this method in mind if I ever code something as prominent as yahoo or twitter or anything else with such a high volume.

    It looks like they’re both using soild color backgrounds and floated divs though. For the yahoo design this method may be applied, but I’m not sure how it’s possible to design something like Twitter’s design using borders because of the way the left and right columns look.

    0
  97. 97

    Francois,

    The fact is, both tables and CSS floats were not designed for layouts. That’s the sad part of CSS — that there’s nothing that is inherently beneficial to multi-columned layouts.

    But when you say that speed doesn’t matter in a non-nested table, you’re assuming quite a bit there. If you don’t nest any tables, and if you only use a simple 3-column layout, then yeah, maybe speed wouldn’t be affected.

    But that’s not how websites are today. Many sites go way beyond the fold (adding to page length, making the tables load slower) and making things harder to maintain.

    And who’s to say that people aren’t going to nest tables? If you’re going to end up using CSS-style blocks inside of the table anyhow, then what’s the point of the table in the first place? If it’s just for the purpose of the 3-column display, then I think the solutions shown in this article are perfectly acceptable, and there is no reason to use a table.

    But I do respect your opinion here. If you really think there’s a case for using a simple table layout, and you think you can make it work, I would love to see a detailed article describing that. Send it to SM so we can all read it! :)

    4
  98. 98

    @Markus Agreed. This is a best practices blog with tutorials. If you feel like you have nothing to learn, then what are you doing here?

    4
  99. 99

    Hi Niels,
    Thanks a lot for the link. You’re right, even though Stu uses two extra wrapper divs to create the layout, it is still the same technique.

    This article should not be a total waste though… As it shows how to do it with three less divs (no wrappers and no need for a empty div to clear the columns). Also, it does not put the main content box last in flow.

    Thanks for posting this and kudos to Stu!

    -1
  100. 100

    Witch method do they use ?

    Table markup :-)

    2
  101. 101

    Hi John,

    The twitter page could use this technique with no problem at all, but note that I am talking about the classic version here.
    I’d tried the new version once, did not like it, and went back to the old version. I don’t remember what the new version looks like, but the classic one is a simple two column layout (table markup).

    -1
  102. 102

    @Thierry I was referring to the Twitter home page, the interiors could use this method.

    I never noticed that Twitter uses tables on it’s interior pages. I wonder why they went that route. Usually I think of tabular data as a table of info, now I’m wondering if a list of tweets are “data” which is almost philosophical.

    0
  103. 103

    @Komb

    That sounds like an excellent idea.
    I’ll investigate :-)

    0
  104. 104

    The content in the left column is generally less important than that in the center column and those using screen readers (if not given the proper tools) now have to scroll through a lot more useless stuff.

    This solution is “source order agnostic” since all columns are floated.

    I do not like cheating with the source order though as it messes up with keyboard user experience.

    As a side note, screen reader users have a mental model of common layouts. For example it is common to find a navigation list before the main content past the header (i.e. vertical navigation in the left column is a very common design).

    As a side note, content order is not only an issue for AT users, as keyboard users face the same problem. Authors can always use skip links and assign ARIA landmark roles to each region.
    See http://www.w3.org/WAI/PF/aria-practices/

    0
  105. 105

    Hi David,
    I’ve tested this in many browsers and found it pretty solid. So I’d be curious to know which “old” browsers you’re referring to.
    And which method? Using body as a wrapper or using negative margins?

    Thanks for your feedback.

    1
  106. 106

    Is it possible to use this markup with the ‘FooterStickAlt’ solution?

    I don’t know about the “FooterStickAlt” solution, but this technique should work as long as the columns are in the same block formatting context.

    1
  107. 107

    I posted earlier.

    Also that “tables are used for data” argument is not enough for me.

    I have worked with divs a lot and Im still far from comfortable with them. Specially giving divs valign middle, top, bottom.. what have you. Always got to read 100 threads on google. Tables, however, simple as hell.

    Also, people, take it easy. Quit downboating and give reasonable arguments. Sure, divs are the moral high-ground, but I
    m so sick of working my ass off to “do the right thing” and for “pretty code”.

    2
  108. 108

    Do you really think a 4kb (even a 12kb) image used throughout the entire website is “expensive”? I’ll agree with John. This technique is interesting, but in the real world I’ve never designed or coded a site that would make use this.

    3
  109. 109

    @Jack

    With the demo page showing in your browser, try “Menu” > “Save as” (or “save page as”).
    That should do it.

    0
  110. 110

    Using negative margins & within IE7 & 6 as always.

    Myself & other members of our team don’t use negative margins but we have had overflow work & a few of the freelancers we work with do. I see the benafits & i see the flaws but like i said before having a wrapper div works & is less code.

    Simple is some times best

    -1
  111. 111

    Your comment in short: “I’m a lazy bum”

    Just because Tables are easier for you to handle doesn’t make it the right choice, now does it?

    -7
  112. 112

    Tables for tabular data is also about accessibility and the use of Assistive Technologies on the web. A properly marked up tabular data table tells a user what the column/row is labeled, how it relates to other headers (if complex) and what the current data is. When it’s a design use, it’s not giving all the data information but it still announcing (table, 3 columns, column 1 and so forth). Not fun to listen to.

    The other issue of semantics is that a table isn’t semantic unless you’re using it’s tags and attributes correctly. How can you be if it’s for design?

    Both of these reasons are clearly stated in the WCAG 2.0 (Web Content Accessibility Guide) and is worth getting familiar with. There are many agencies, schools, etc. that won’t use a product if it’s service web site doesn’t meet guidelines, so you lose customers.

    2
  113. 113

    The section “Further reading”, at the end of this article, already contains a link to this site. :-)

    0
  114. 114

    Not having to use JavaScript is nice and welcome, however in today’s word there isn’t many sites I wager that do not use JavaScript/jQuery at all. With that in mind, if you are using JavaScript period it is already loaded in the cache and available to you. Further I would wager if you are using a jQuery plug-in to help with matching the heights, you probably would be using it throughout the site in the long run for other purposes too, lowering it’s footprint as a whole again due to a ROI type of deal from the initial load that is now in the cache.

    I am not saying a purely css method is not very appealing, it just has a very niche placement and use I figure when you look at the bulk of design and architecture of sites being done today.

    Just my 2 cents.

    2
  115. 115

    Hi Paul,

    bottom:0;
    top:0;

    Yes, we can stretch the box using absolute positioning, don’t we all use this technique for overlays?
    What happened here is that the original demo was using extra markup to make things work in IE 6/7, but IE6 does not stretch the box, hence why I’d styled the “companion columns” [1] with a height. When I changed my mind and preferred to go with minimal markup, going with the Nicolas Gallagher method, I did a simple copy/paste, without “revisiting” the logic… :-(

    I do have qualms about using the body element as a wrapper though as it throws the zoom right out in IE7

    Do you mean when hitting Ctrl ++ (on Win)? Do the demos exhibit this issue? Because I cannot reproduce this in IE7.

    As a side note, I could not have link to Doug Livingstone’s page [1] (nor to Stu Nichols one [2] for that matter), for the simple reason that I was not aware of their work. Like always, I research for prior art, but nothing like that turned up. Not even in articles discussing the different techniques (i.e. the recent “Fluid Width Equal Height Columns” on CSS-Tricks). Everything I found on the subject at the time is listed in the Further reading section on this page.

    Regarding the wrapper-less approach, I agree with you that it does not worth the effort. But this article is not about creating a template, it is rather about exploring different ways to do things.

    Thanks for stopping by and sharing your thoughts.

    [1] http://www.satzansatz.de/cssd/companions.html
    [2] http://redmelon.net/tstme/3cols2/
    [3] http://www.cssplay.co.uk/layouts/3cols.html

    0
  116. 116

    @martin, i have been using same solution but there is a problem. If there is any anchor tag (internal link) in page, page format will break on click on link.

    Love the provided solution in this article ! This problem is not in this solution . Its much better then other solution of equal columns.

    1
  117. 117

    Is there any problem if we use styling of a div container on place of body?

    No, that’s not a problem at all. Using a wrapper may make your life easier actually :-)

    0

↑ Back to top