Flexible Containers – Tables are back! (Sorta…)

Back in the Paleolithic days of the Web, if you wanted to make a website that was anything but linear, your only choice was to turn to the <table> tag. In fact, most swanky sites back then were table-based layouts nestled with sliced images.

Coding practices shifted after the introduction of cascading stylesheets (CSS). Front-end developers began thinking about markup in terms of its semantics. Web standards arose and we moved to using floating elements to make layouts, lest we be berated by the standardistas. In this new semantic world, <table> was relegated back to its lowly task of being the Web’s spreadsheet.

Many useful things were lost when table-based layouts went out of fashion – features like vertical-centering of content and height-matching on columns. Instead, floating-element layouts introduced a host of issues, such as collapsing containers, margin bugs, and elements that mysteriously wrapped.

One of the more useful things table-based layouts had was flexibility. Because table-cells have an implicit relationship, they accommodate width changes and don’t break apart. Floating elements have no interrelationship. To share horizontal space fluidly, widths must all be percentages (no mixing of units). Even then, cross-browser, you’ll see that subpixel rendering is handled differently in each browser. Your columns wrap in IE while being too narrow in Webkit.

Despite drawbacks, we cannot go back to using tables for layout. The web is consumed by so many devices and parsers that there’s no room for presentation-only markup, which is what the table-based layout is. And yet, there are no good ways to make elements flexible.

Fast-forward to the near-future. Available to us, very soon, is a new set of CSS3 selectors, aptly called “flexbox” (flexible box layout module), that will help us in our quest for flexibility. Flexbox gives elements implicit relationships; it delivers many of the things we miss about tables, and it even gives us cool new features.

Let’s take a look at some code. Albeit HTML5, this snippet is the 3-column pattern we’re all familiar with…

HTML

<section>
<nav>The nav is here!</nav>
<article>I’m the article.</article>
<aside>BTW, I’m an aside.</aside>
</section>

Now check out the styles…

CSS

/* First, some basic styling… */
section {
width: 100%;
height: 100%;
}
nav,
article,
aside {
padding: 30px;
}
nav,
aside {
background: #ccc;
width: 200px;
}
article {
background: #eee;
}
/* Now, the flexbox magic… */
section {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
article {
-webkit-box-flex: 1;
-webkit-flex: 1;
-moz-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
nav, article, aside {
-webkit-box-align: center;
-moz-box-align: center;
box-align: center;
}

We now have a layout that’s both fluid and contains fixed-pixel elements. The columns match height, and the content is centered. But this example is just the tip of the iceberg. Flexbox’s powerful specs also include the ability to reorder and distribute elements, change layout orientation, and more. It is a boon for creating responsive layouts.

One thing you may have noticed in the CSS is the mix of display values (box vs. flex vs. flexbox). Although flexbox is a candidate for recommendation, the browser vendors haven’t synced-up to the standard. To complicate matters, the syntax was changed after it was implemented by some vendors (like what happened with CSS gradients). It’s a mess, but soon we’ll use flexbox more commonly.

In the meantime, there is a CSS 2.1 way to mimic flexbox’s superpowers. It’s a method even IE8 supports: {display: table;}. Allow me to demonstrate…

Using the flexbox example above, replace the flexbox-specific CSS with this…

/* Table magic… */
section {
display: table;
table-layout: fixed;
}
nav,
article,
aside {
display: table-cell;
vertical-align: middle;
}

You now get the same effect: fluid layout with fixed-pixel elements, height-matching columns, and centered content. And, you can use it today! But this method is not without issue. Just as if you were using <table> tags, you won’t be able to apply border-radius to the container and have it clip the background of child elements. Also, child elements, being table-cells, will be controlled by the cell-width algorithm (though this is mostly solved with {table-layout: fixed;}). All said, it is a small price to pay for a semantic, flexible layout.

This is a guest post by Jim Green

For over 15 years, Jim has lead UX design for both small agencies and large corporations. A leg in both the art and the science, he is not just a seasoned UI designer but also a certified usability tester and field researcher. Jim is focused on process improvement, having developed a rapid prototyping tool and UX processes for his current organization. An unconventional thinker and life-long rabblerouser, Jim continues to be called to the principal’s office.

Jim Green Headshot