Blog

Solving the Holy Grail Layout

Searching for the elusive Holy Grail of CSS layouts has lead to many clever solutions, but never has there been a single solution that doesn’t involve hacks or drawbacks. Tables, divs with table-property displays, and absolutely positioned divs are some of the ways we’ve accomplished the Holy Grail layout in the past. With the introduction of Flexbox though, we can end our search for the Holy Grail of web layouts. With the power of CSS3, the once highly sought after solution has been found.

The Flexible Box Layout Module, more commonly known as Flexbox, confronts many layout issues head-on, including the Holy Grail layout. So just what is the Holy Grail layout?

The Holy Grail layout is simply a multiple (usually 3) column layout with fixed widths for the first and last columns and a fluid width for the center column. Setting explicit widths on the outer columns is what makes the layout tricky, because we can’t calculate the width of the center column (well, technically we can using the CSS calc property, but we’ll save that for later). If we just used percentages for the outer columns, we could easily achieve a fluid layout. But we’re after the Holy Grail, remember?

Ending the Holy Grail search

To start off with, we have to set the display property to flex on a containing element. Just like we have block, inline and inline-block values for the display property, we now have flex. For the sake of a simple example, we’ll just use the body as our only containing element.

body {
  display: flex;
}

This now sets us up to start using the different Flexbox properties. There are about 13 different properties available that you can check out in full in the W3C spec, but all we need for our layout is the flex property.

<nav></nav>
<section></section>
<aside></aside>
html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
}

body {
  display: flex;
}

nav,
aside {
  flex: 0 0 12em;
}

That’s it! With that simple bit of code we have a left navigation sidebar, a middle content section and a right sidebar. The nav and aside elements each have a width of 12em and the section element has a fluid width that flexes between the nav and aside. Notice we didn’t even need to set any properties on the section element.

So what’s behind the flex values?

It’s easy enough to see how this works, but WHY is it working? Why is the section flexing its width between the nav and aside elements? Well, the flex property is actually shorthand for flex-grow, flex-shrink and flex-basis.

So this:

flex: 0 0 12em;

Is shorthand for this:

flex-grow: 0;
flex-shrink: 0;
flex-basis: 12em;

Setting flex-grow and flex-shrink to 0 prevents the elements from, you guessed it, growing and shrinking. And setting flex-basis to 12em defines the width.

The good news?

You can use Flexbox today in the latest versions of most modern browsers.

can-i-use-flexbox

Source: caniuse.com

The bad news?

We’re still a ways away from being able to rely on Flexbox in a wide variety of browsers. The syntax has changed several times since it first came out, so to get support in IE10 and other older browsers, we have to use some different vendor prefixes.

display: -moz-box;      /* OLD: Firefox (buggy) */
display: -ms-flexbox;   /* MID: IE 10 */
display: -webkit-flex;  /* New: Chrome 21+ */
display: flex;      /* NEW: Opera 12.1, Firefox 22+ */

None of the properties work in IE9 and below and Safari and Firefox have varying levels of support. Our example above, for instance, renders a 3 row layout in Safari 6. However, we can always provide float and width fallbacks for older browsers.

CodePen example

Tweet about this on TwitterShare on FacebookShare on RedditShare on Google+Share on LinkedIn

  • Pingback: Best of JavaScript, HTML & CSS – Week of March 10, 2014 | Flippin' Awesome

  • http://webplatformdaily.org Šime Vidas

    “…we have to use some different vendor prefixes” – This makes it sound like we (developers) have to manually write those vendor-prefixed properties. In reality, we only have to write the final unprefixed syntax and let tools like Autoprefixer fill in the gaps.

  • http://dpashk.com/ Dmitry Pashkevich

    Another important point I would mention is that the spec allows you to easily change the order of your columns without touching HTML code, thus fully decoupling the visual ordering from the “physical” one. There are know reasons why you may want the two to be different.

    See https://developer.mozilla.org/en-US/docs/Web/CSS/order

  • http://dpashk.com/ Dmitry Pashkevich

    Great interatcive tutorial on flexbox

    http://devbryce.com/site/flexbox/