Use CSS display:table for Layout

Posted on: Sunday, February 15th, 2009 at 11:34 pm

I had this post in draft since October 2008. I thought I’d redesign this blog site using display:table and explain that in a series of posts, starting with this one. But I never found the time for the redesign!

Still, I have been using display:table on a much larger site for about 6 months now, so I thought I might as well post this as it is, and perhaps follow up with more examples later.

Also, about 3 weeks after I started this draft, Rachel Andrew and Kevin Yank wrote a book on CSS display:table for layout, as well as a useful summary article! I do recommend looking at that article for finer details.

No need for css float for layout in modern browsers

For a few years now, web developers doing CSS-based layouts have used floats or absolute positioning for layout web sites to avoid using non-semantic HTML <table>s.

While doable, extra hoops often have to be jumped through (mostly for IE) and some seemingly simple things can be harder than necessary (like equal height columns).

However, for a simpler solution, CSS-based display:table, display:table-row, display:table-cell etc are all usable today across Firefox 2+, Safari 3+, Opera 9+ and IE8.

Example:

Consider the following HTML:

<body>
	<div id="header">
		<!-- header -->
	</div>

	<div id="content-body-wrapper">
		<div id="content-body">
			<div id="primary-nav">
				<!-- some navigation column here -->
			</div>
			<div id="secondary-nav">
				<!-- some additional column here -->
			</div>
			<div id="content">
				<!-- main content here -->
			</div>
		</div>
	</div>

	<div id="footer">
		<!-- footer -->
	</div>
</body>

And the CSS to style it to get equal height columns:

#content-body-wrapper {
    display:table;
    border-collapse:collapse;
}

#content-body {
    display:table-row;
}

#primary-nav, #secondary-nav, #content {
    display:table-cell;
}

#primary-nav, #secondary-nav {
    width:20%;
}

#content {
    width:60%;
}

And that’s it!

The above is just the layout bit of the CSS. Here are some screenshots (click for full size) with content and very basic styling just to see the equal height column effect:

The first is with Firefox 3 and the second with IE8.

You can actually omit extra divs, even the one that gets display:table and the browser is required to create an anonymous table for you.

Isn’t using table for layout wrong?

This is not the same as using the structural html table elements for layout purposes — that indeed is an inappropriate use for tables.

This is using CSS to give table-like display, which is fine as it leaves the HTML (and document structure) in tact.

What about IE 7 and 6?

IE7 and 6 of course remain problems, but you can use conditional comments and give them older techniques that attempt to achieve this.

Some limitations or issues

Some limitations of css display:table I have come across, however, include these:

  • Lack of colspan/rowspan equivalents
  • Like HTML tables, a CSS cell can expand in width based on content (as well as height).

On the last one I noticed this when using things like <pre> even with overflow:auto with the thought that just like inside floated columns with widths assigned this would result in those <pre> blocks getting horizontal scrolls if they became too wide.

Instead, as with HTML tables, they push out the cell they are in. The only workaround I knew to this was to give a px or em width to such elements. (It also applies to large images in a cell.)

That being said, display:table seems a lot cleaner!

CSS3 has an advanced layout module in the works but there are not any browser implementations of it (that I am aware of), so in the interim this could be a useful approach.

More info

Share this

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Furl
  • Ma.gnolia
  • NewsVine
  • Reddit
  • Slashdot
  • StumbleUpon
  • Technorati
  • YahooMyWeb
  • Facebook

About this post

Post Navigation

7 Responses to “Use CSS display:table for Layout”

  1. On February 25th, 2009 at 5:32 pm AaronSieb said :

    I’ve been playing with this technique as well, but there’s something about it that bothers me…

    If you take the main portion of your markup, and convert the DIVs into appropriate tags, we end up with this structure:

    That’s the same number of tags, with the same number of CSS hooks. How is this any worse than the same set of DIVs? Especially when you consider that THIS structure is supported by the most popular browsers on the ‘net?

    I just wish there was a way to access the display: table-cell behavior, without needing to nest it inside of display: table and display: table-row… The extra markup overhead is enough to make me question CSS.

  2. On February 25th, 2009 at 5:34 pm AaronSieb said :

    Aaand, it ate my markup. Hopefully this shows up as somewhat readable.

    <table id=”content-body-wrapper”>
    <tr id=”content-body”>
    <td id=”primary-nav”>
    <!– some navigation column here –>
    </td>
    <td id=”secondary-nav”>
    <!– some additional column here –>
    </td>
    <td id=”content”>
    <!– main content here –>
    </td>
    </tr>
    </table>

  3. On April 2nd, 2009 at 10:48 am Sanjeev said :

    Hi,

    What is the exact fix for IE 6, I tried it in mozilla and i was really happy by seeing the output. Please can anyone provide the fix for IE

    Sanjeev

  4. On April 11th, 2009 at 5:21 am Sanjeev said :

    Thanks Anoop,

    Actually i was really trying very hard to find some table layout without using Table then, i come across some techniques…

    left block
    body block
    right block

    * {margin:0;padding:0;}
    #main{display:table-row; list-style-type:none }
    #left,#body,#right {display:table-cell;}

    Its really worked for me

  5. On April 11th, 2009 at 5:26 am Sanjeev said :

    Thanks Anoop,

    Actually i was really trying very hard to find some table layout without using Table then, i come across some techniques

    <ol id="main">
    <li id="main">left block</li>
    <li id="main">body block</li>
    <li id="main">right block</li>
    </ol>

    <style>
    * {margin:0;padding:0;}
    #main{display:table-row; list-style-type:none }
    #left,#body,#right {display:table-cell;}
    </style>
    Its really worked for me

Post a Comment