5

I have a table set to 100% width whose columns I would like to acquire defined widths. However, all my columns seem to get equal widths.

.table {
  table-layout: fixed;
  width: 100%;
}

.table th[colspan=4] {
  /* width: 100%; */
}

.table td,
th {
  border: 1px solid #AAA;
  text-align: center;
}

.table td.one {
  width: 10%;
}

.table td.two {
  width: 20%;
}

.table td.three {
  width: 50%;
}

.table td.four {
  width: 20%;
}
<table class="table">
  <tbody>
    <tr>
      <th colspan="4">All Four</th>
    </tr>
    <tr>
      <th colspan="4">All Four</th>
    </tr>
    <tr>
      <td class="one">A</td>
      <td class="two">B</td>
      <td class="three">C</td>
      <td class="four">D</td>
    </tr>
  </tbody>
</table>

If I remove the width property on the table, it honours the individual column widths. If I change the layout to table-layout: auto, then also it works. But I just cannot get the widths to be what I want them to be if I have a row that spans multiple columns as the first row.

adarshr
  • 61,315
  • 23
  • 138
  • 167
  • this ? http://stackoverflow.com/questions/5938099/html-table-cell-width-for-different-rows – Stavm Mar 14 '17 at 11:29
  • No it's not that. I am not after having different widths for different rows. It's about coexisting colspan and unique widths in a 100% width table with fixed layout. – adarshr Mar 14 '17 at 11:30

2 Answers2

7

If I remove the width property on the table, it honours the individual column widths. If I change the layout to table-layout: auto, then also it works. But I just cannot get the widths to be what I want them to be if I have a row that spans multiple columns as the first row

That is how the table-layout: fixed works.

From here: https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout

Table and column widths are set by the widths of table and col elements or by the width of the first row of cells. Cells in subsequent rows do not affect column widths.

And from here: https://www.w3.org/TR/CSS21/tables.html#fixed-table-layout

In this manner, the user agent can begin to lay out the table once the entire first row has been received. Cells in subsequent rows do not affect column widths.

So, in effect:

  1. If you change the layout to auto, it will use the automatic table layout and your column widths take precedence over the content size.
  2. If you remove the width property on a table, then it ceases to use the fixed table layout and is as good as auto.

The other answer works because the width property is removed (just as you mentioned in your question). If you refer back to the specs linked above, it says:

The table's width may be specified explicitly with the 'width' property. A value of 'auto' (for both 'display: table' and 'display: inline-table') means use the automatic table layout algorithm.

Solution:

The solution to your problem is to somehow get the table layout to ignore the first row. This is done by the colgroup / col elements. Remove the classes which define the widths on the td, and specify those on the cols.

Snippet:

.table { table-layout: fixed; width: 100%; }
.table td, th {
  border: 1px solid #aaa; 
  text-align: center; padding: 4px;
}
.table col.one { width: 10%; }
.table col.two { width: 20%; }
.table col.three { width: 50%; }
.table col.four { width: 20%; }
<table class="table">
 <colgroup>
  <col class="one"/>
  <col class="two"/>
  <col class="three"/>
  <col class="four"/>
 </colgroup>
  <tbody>
    <tr><th colspan="4">All Four</th></tr>
    <tr><th colspan="4">All Four</th></tr>
    <tr>
      <td >A</td>
      <td >B</td>
      <td >C</td>
      <td >D</td>
    </tr>
  </tbody>
</table>
Abhitalks
  • 27,721
  • 5
  • 58
  • 81
5

To be honest, I can't exactly you tell you "why". But if you change the width: 100%; to min-width: 100% you get the desired result. I guess it's because if you set the width to 100%, the overall width of each column can not be calculated.

.table {
  table-layout: fixed;
  min-width: 100%;
}

.table th[colspan=4] {
  /* width: 100%; */
}

.table td,
th {
  border: 1px solid #AAA;
  text-align: center;
}

.table td.one {
  width: 10%;
}

.table td.two {
  width: 20%;
}

.table td.three {
  width: 50%;
}

.table td.four {
  width: 20%;
}
<table class="table">
  <tbody>
    <tr>
      <th colspan="4">All Four</th>
    </tr>
    <tr>
      <th colspan="4">All Four</th>
    </tr>
    <tr>
      <td class="one">A</td>
      <td class="two">B</td>
      <td class="three">C</td>
      <td class="four">D</td>
    </tr>
  </tbody>
</table>
Nico O
  • 13,762
  • 9
  • 54
  • 69
  • The Op mentioned that they already know this -- "*[..]If I remove the width property on the table, it honours the individual column widths[]..*" – Abhitalks Mar 14 '17 at 11:57
  • @Abhitalks that is correct. But it seems OP wanted a width of 100% and happen to struggle with an alternative way of declaration. Hence this should be the desired solution imho. – Nico O Mar 14 '17 at 11:59
  • Ahh.. ok, fair enough Nico. Thanks. I thought, you missed that. Deleting my comment in 5 secs. – Abhitalks Mar 14 '17 at 12:00
  • 1
    @Abhitalks no harm was done. You can let your comment there, since your point is valid. – Nico O Mar 14 '17 at 12:01
  • Thank you for your answer. I had gone with your answer until @Abhitalks nailed it :-) – adarshr Mar 14 '17 at 15:01
  • 1
    @adarshr thank you for your feedback. You made the right choice. My answer is not as complete as the provided and rightfully accepted one – Nico O Mar 14 '17 at 15:42