Sangraal layout: A true flexible, fluid CSS layout
The wait is over, finally a real ’sangraal’ layout that ticks all the boxes:
- 3 column, 2 column, 1 column it’s all flexible
- Fluid centre layout
- No need for negative margins.
- Works in ie5+, firefox 1+, opera 9.6+, safari 2+, chrome
- Minimal mark-up & clean CSS
With inspiration coming from A List Aparts’ article ‘In Search of the Holy Grail‘ but with a need for a better way without the use of negative margins to help pull the main content back into place. Making it a much more powerful, flexible layout with a much easier setup. Let’s take a look at an example before we delve into the inner workings.
The xhtml
<div class="maincontainer"> <div class="column01"> <div class="restraint"> <p>Left column</p> </div> </div> <div class="column03"> <div class="restraint"> <p>Right column</p> </div> </div> <div class="column02"> <div class="restraint"> <p>Middle column</p> </div> </div> </div>
The CSS
.maincontainer { position: relative; overflow: hidden; } /* Left column */ .maincontainer .column01 { float: left; } /* Width is set in inner div of column to avoid the use of negative margins */ .maincontainer .column01 .restraint, .maincontainer .column03 .restraint { width: 200px; } /* Left column */ .maincontainer .column03 { float: right; } /* Middle column */ .maincontainer .column02 { overflow: hidden; } .maincontainer .column02 .restraint { width: 100%; } * html .maincontainer .column02 { /* cause hasLayout so middle column will sit between left and right */ display: inline-block; }
How it all works
This layout is quite ingenious, it’s very simple and extremely flexible. The containing div isn’t essential for the layout to function. However, it is a good idea. Containing it will allow for easy selection in the CSS and prevent issues with inheritance. You’ll notice that the left and right column appear before the main content container, this is needed for the layout to work. In each column there is a restraint div. The magic of this layout is in the restraint div setup; columns 1 & 3 are floated left and right respectively and column 2 is set with a hidden overflow. This allows for column 2 to appear between the left & right columns. The restraint divs can now be used to set the widths of the columns. Columns 1 & 3 have pixel widths set, column 2 is then set with 100% width so it will fill the remaining space. Having the widths set inside the columns allows for this layout to work. If you have ever floated an image near a paragraph you’ll understand how this is working, by placing the 2 floated divs before the block level element will cause it to wrap around the floated elements. This setup has 1 difference if the middle column is longer than the other columns it will not wrap but rather keep it’s width and not overflow into the left & right columns this is due to the hidden overflow on the middle column, without it the middle column would behave as expected and wrap underneath the left and right columns. The * html selector is used to give column 2 layout in IE6, this is the least destructive hasLayout property in our case. Without this, the middle column would appear below the left & right columns.
Here we have a very flexible layout, I highly suggest you mess around with it and see the true power e.g. removing the left, right or both columns won’t break the layout, and the middle column will expand to take up the extra space. Adjusting the left and right column widths will also make the middle column adjust to the space it has to work with. I believe this to be the most powerful layout available. Have a play with this example, there are 2 input fields which dynamically adjust the left & right column widths.
One thing to make it perfect
There’s one last thing to make this perfect, if you have been playing with the demos you may have noticed that resizing the window to a small width breaks the layout and eventually causes the middle column to behave oddly.

What we need is a cross browser min-width and if you take a look at my last article "A look at pure CSS IE6 min-width solutions" we have the perfect solution using padding to accomplish just that.
The xhtml
<!--[if IE 6]> <div class="min_width"> <div class="min_width_inner"> <div class="min_width_container"> <![endif]--> <div class="maincontainer"> <div class="column01"> <div class="restraint"> <p>Left column</p> </div> </div> <div class="column03"> <div class="restraint"> <p>Right column</p> </div> </div> <div class="column02"> <div class="restraint"> <p>Middle column</p> </div> </div> </div> <!--[if IE 6]> </div> </div> </div> <![endif]-->
The CSS
/* Min -width styles */ .min_width { padding: 0 480px; text-align: left; } .min_width .min_width_inner { width: 100%; /* gives the element hasLayout */ } .min_width .min_width_container { margin: 0 -480px; position: relative; float: left; } /* Sangraal layout styles */ .maincontainer { position: relative; overflow: hidden; min-width: 960px; /* For good browsers */ } /* Left column */ .maincontainer .column01 { float: left; } /* Width is set in inner div of column to avoid the use of negative margins */ .maincontainer .column01 .restraint, .maincontainer .column03 .restraint { width: 200px; } /* Left column */ .maincontainer .column03 { float: right; } /* Middle column */ .maincontainer .column02 { overflow: hidden; } .maincontainer .column02 .restraint { width: 100%; } * html .maincontainer .column02 { /* cause hasLayout so middle column will sit between left and right */ display: inline-block; }
If you refer back to the "A look at pure CSS IE6 min-width solutions" article you’ll see how the min-width works in IE6. There is only 1 slight difference with this, the actual min-width property is on the .maincontainer div and not the .min-width div. The min-width mark-up has also all been moved within the IE6 conditional comments so it will only render for IE6 and not cause any problems with the good browsers.
A layout to remember…
This layout isn’t perfect but it comes damn near close. It is a little heavy on the mark-up but for what it accomplishes I think that’s ok. The order of the div’s will also be a concern to some especially those using screen readers as going from the left to right to middle may disorientate some.

Sangraal is indeed an ingenious layout.
However, the problem I have with it is that if you use different background colors in each column, the colors don’t fill down to the bottom of the tallest column. The layout is dynamic in width, but not in height.
The only way I know to accomplish a true 3 column fluid layout where all columns are all the same height and dynamic, is with a table. I observe that sangraal has the same nesting depth of div tags as a table, so a table isn’t really a more complex layout.
-Alex
Anachronist, July 10th, 2009Easy fix, use a background image on the body or the container div to fake the background extending evenly. See faux columns.
Never use a table for layout, a table should only be used for it’s intended purpose of displaying tabular data. If you really want the ease of tables in your layout take a look at the CSS table property.
The Css Ninja, July 10th, 2009Using a background image to give the illusion of column borders forces you to have non-fluid, fixed width columns that conform to the image. That isn’t a solution, especially if you want a border surrounding the dynamic-width columns.
A few years ago when I experimented with the CSS table property, I wasn’t happy with the results on the browsers available at the time, particularly IE and Opera. I’ll have to revisit that.
So, is it possible to have the flexibility of this Sangraal layout with columns that truly are all the same height, and change height dynamically?
“Never use a table for layout” is a philosophical position with which I respectuflly disagree. My vew is, if you want something that behaves exactly like a table, then use the right tool for the job. I have found that the markup for a 2- or 3-column table is often simpler and more straightforward than the div soup one must create to accomplish the same behavior.
Anachronist, July 11th, 2009Not off the top of my head but I will investigate into this.
Web development is as much about making designs look right as it is making it flow right. We as web developers need to cater for so much more. Try going through one of your table based layouts with a screen reader you’ll truly see that tables should never be used for layout and is certainly not a philosophical position, but rather the correct position.
The Css Ninja, July 11th, 2009Thanks for the response. I’ll only rebut that a good web designer can also make column-table layouts comprehensible in a screen reader.
Anachronist, July 13th, 2009Arigato gozaimasu, Ninja san
this was straight to the point, just what I needed.
LindsayK, December 22nd, 2009