Tables are hard

April 3, 2014

Let’s talk about HTML tables.

Here’s some code:

<table class="main">
  <colgroup><col class="votes"><col></colgroup>
  <tr>
    <td>Votes</td>
    <td>Comments</td>
  </tr>
  <tr>
    <td>
      <p class="vote-desc">Some long name, really long, like really super long</p>
      <p class="vote-desc">Another long name, really long</p>
    </td>
    <td>
      <p class="comment">A really, really, really, really, really really really really really, really long comment.</p>
    </td>
  </tr>
</table>

In this table, there are two main data cells: one with two vote descriptions and one with a comment. Assuming the outside of the table has a constrained width, what will be the widths of the two inner data cells? Check out this jsfiddle. Now, check it out with a longer comment.

When I came across this situation in a project I was working on, I expected the left column to set its own width based on the width of its content, and for the subsequent columns to do the same with the remaining space. But no! In chrome and firefox, the left cell is all squished up, but the crazier thing is that chrome and firefox squish it up differently.

Non-normativity

It turns out that this part of the HTML specification is actually non-normative. It’s called the automatic table layout algorithm. Basically, this applies to tables (elements with display: table or display: inline-table) with table-layout: auto. [See end note.] From the spec:

"UAs are not required to implement this algorithm to determine the table layout in the case that ‘table-layout’ is ‘auto’; they can use any other algorithm even if it results in different behavior."

So, this is what really happens: the browser doesn’t know what to do when there are two columns that have to have automatically distributed width, so it makes its own decision.

What to do?

In order to control the actual width of columns in a table, we have a couple of options. Since, according to the spec, setting table-layout: auto can have unpredictable results, we should use table-layout: fixed if we’re not sure of the length of the content that will occupy the table cells.

In this case, the browser will try to determine the width of the columns first by the widths of the column elements, second by the width of the cells in the first row of the column, and third by distributing total table width, if it is set, equally among columns (note that if it is not set, then the automatic table algorithm from above will be used, in some cases [see end note]). This is called the fixed table layout algorithm.

Here’s an example: much better!

End note

The specification is a little shaky on what kind of algorithms should be used when for table width. Steps go like this, for a table or inline-table element:

  1. If the table has table-layout: auto, use the non-normative auto algorithm.
  2. If the table has table-layout: fixed and has a width set, then use the normative fixed algorithm (aka, distribute equally) based on that width.
  3. If the table has table-layout: fixed but does not have a width set, then what to do depends on whether the element is a table or an inline-table.
    1. If the latter, use the auto algorithm.
    2. If the former, either use the auto algorithm, or calculate the total width of the table based on the normal block flow, then use the fixed algorithm based on that width.

That is, the widths could still be non-normative if you use a fixed layout table with an automatic width. Maybe.

Tables are hard.

Picture of me with a corgi

Noah Gilmore

Hello! I'm Noah, a software developer based in the San Francisco bay area. I focus mainly on iOS, Apple platform development, and full stack web development.

  • 💻 I'm writing a macOS editor for Atlassian Confluence called Fluency
  • 📱 I wrote an app which lets you create transparent app icons called Transparent App Icons
  • 🧩 I made a puzzle game for iPhone and iPad called Trestle
  • 🎨 I wrote a CoreImage filter utility app for iOS developers called CIFilter.io
  • 👋 Please feel free to reach out on Twitter