Grow your CSS skills. Land your dream job.

Fixed Table Layouts

Published by Chris Coyier

There is a CSS property for tables that, it seems to me, is well-supported, little known, and super useful. It changes the way that tables are rendered such that it gives you a sturdier, more predictable layout.

It is this:

table {
  table-layout: fixed;
}

The default property for table-layout is auto, and that is the table layout I think most of us are familiar with. That style, to me, feels spongy and weird. Here's an exploration:

See the Pen Default Tables are Weird. by Chris Coyier (@chriscoyier) on CodePen.

With table-layout: fixed;

Things get a lot sturdier and more predictable with property/value in place.

The layout is fixed based on the first row. Set the width of those, and the rest of the table follows.

It's a little more complicated, but not much. Here's an exploration:

See the Pen Fixed Tables Solve Some Issues by Chris Coyier (@chriscoyier) on CodePen.

Use Case

I explored this because I was trying to keep a uniform row height for Pens in list view on CodePen (i.e. not wrap Pen titles) but also not blow out the width of the table. This worked great.

I imagine most of you know this: tables are for tabular data and emails. Not web layouts, because reasons.

Practical HTML and CSS

I imagine most uses will be like this:

<table class="users">
  <thead>
    <tr>
      <th class="row-1 row-ID">ID</th>
      <th class="row-2 row-name">Name</th>
      <th class="row-3 row-job">Job</th>
      <th class="row-4 row-email">Email<th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0001</td>
      <td>Johnny Five</td>
      <td>Robotin'</td>
      <td>need@input.com</td>
    </tr>
    <tr>
      <td>0002</td>
      <td>Super Superlonglastnamesmith</td>
      <td>Doin' stuff</td>
      <td>doing@stuff.com</td>
    </tr>
  </tbody>
</table>
.users {
  table-layout: fixed;
  width: 100%;
  white-space: nowrap;
}
.users td {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Column widths are based on these cells */
.row-ID {
  width: 10%;
}
.row-name {
  width: 40%;
}
.row-job {
  width: 30%;
}
.row-email {
  width: 20%;
}

See the Pen xFcrp by Chris Coyier (@chriscoyier) on CodePen.

For good measure, know that you can use the <col> element to set column widths too, because those effect the first row of cells and it's all about that first row of cells setting the basis for the rest of the table.

Layout Speed

I've heard that this style of table layout is faster as well, which stands to reason because the contents of the entire table don't need to be analyzed to know how big column widths are going to be. I don't have any data on that though.

In Emails

Campaign Montior's support chart for CSS in email clients shows table-layout as being supported across the board.

More Info

Follow Up Tweets

Comments

  1. When doing vertical alignment with display: table; and display: table-cell; vertical-align: middle; on its children, and one of the children contains an “ that you also want to scale and keep its ratio, I’ve had to use table-layout: fixed on the element with display: table; in order for it to play nice in Firefox.

    • Apologies, the typo in my previous comment was supposed to be an img tag.

    • Connor

      Yes, I run into this constantly, vertically centering images with different dimensions in fixed ratio container, like in a product listing grid! The images scale nicely in Chrome, but in FF the images will bust out the container w/o table-layout: fixed.

  2. Travis Holliday

    Awesome as always, Chris. Thanks!

  3. Jesse Trippe

    Great post but how come there’s no mention of colgroups and cols?

  4. For my responsive emails, I only apply this to the outermost table. Otherwise kablooey.

  5. Solomon Hawk

    Hi Chris,

    Thanks for the tip! I had to use this recently as well and it is tremendously useful as you demonstrated clearly here.

    I have a question about the last codepen example (the resizable one with text-overflow: ellipsis.) As you scale the width down, the first column of IDs gets the ellipsis properly. But when I shrink it down to it’s minimum width, the first column of IDs no longer have the ellipsis and instead just show 000 with the rest cut off as if with overflow: hidden.

    Do you have any idea why this is? I’m just curious!

    • I noticed that too! Kinda weird. Maybe it’s like if it can’t fit the ellipsis it defaults back to the text. Which is weird and probably a bug. Or maybe not. Hard to say.

  6. Johan

    I have used this property for 2 projects already, but using it on DIV’s. The beauty is that a child element can have a fixed width, and the rest will just adapt.
    You can see it in action on this page. The timeline at the bottom is made this way.

    http://windpowerpioneers.vestas.com/timeline

    • Vesa Piittinen

      The selected year will wrap to two lines atleast on Firefox when in specific browser widths. This is caused by word-wrap: break-word; which is a star rule. Is there a reason why you’ve applied this? Just seems to me like something that will cause tons of unexpected layout issues.

    • Johan

      Hi Vesa
      You have got a good point. In this example I would remove the word-wrap. But generally I like to have it on the *, because clients tend to write some long words once in a while, or copy a long url to the content.

  7. Nice one Chris.

    Also, something completely different. There seems to be something wrong with your CDN…

  8. Scott

    Regarding: “And I’m 1000px wide. You’d think maybe it would be 1/3 as wide ultimately, but it doesn’t work like that.”

    Isn’t that exactly what it is doing? That column is 1/3 the width of the other one, or 1/4 the width of the whole table (1000px out of 4000px total).

    • Dominic

      For me, it isn’t. It’s smaller than 1/4, exactly as wide as the longest word, which is “ultimately,”.

    • Yeah it actually does work like that.

      I updated the example to be more clear, with one cell being 2000px wide and the other 1000px wide, it ends up 2/3 and 1/3.

  9. keithpickering

    I love table-layout: fixed. I’m still using it as a flexbox alternative until IE8 is safe to forget about. It makes it trivially easy to have a fluid-width item take up the remaining width of the container.

    • ElijahFowler

      IE9 doesn’t support Flexbox either though, are you just planning on jumping IE9 (with the user base being less than IE8) when you leave IE8?

      My company ditched IE8 a long time ago and are getting ready to dump IE9 as well, but the use of table-layout: fixed was something that came in handy at times.

  10. I must be missing something – here’s what my attempt to czech out your code looks like: http://jsfiddle.net/clayshannon/8m8xr/

  11. Add text-align:left property to table element

  12. Ginje

    Using <col> in a table with fixed-layout really comes into its own when cells in the first row use ‘colspan=’.

  13. Wellington Torrejais da Silva

    Thanks!!!

  14. i think table-layout:fixed is equal width

  15. IE9 doesn’t assistance Flexbox either though, are you just preparing on moving IE9 (with the users list being less than IE8) when you keep IE8?

  16. Thank you. I got burnt so often using table layouts in CSS “instead” of the conventional HTML table layouts that I eventually gave up and stuck with the HTML stuff completely. It is articles like yours that don’t use general verbiage without telling something concrete and useful, that I need to make it through “CSS rehab”. My problem is that I have a lot of legace XLS and ODT tables/databases with a lot of material that I wanted to get online and each time I tried it came apart “at the seams”.

  17. Yeah it actually does work like that, Thank you

  18. Johan

    It will

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".