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 ultimate flexible layout example

The xhtml

Left column

Right column

Middle column

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.

Sangraal layout plays up when it goes to small

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


    

Left column

Right column

Middle column

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.