4

I believe the width: 1px; white-space: nowrap; trick worked before but it seems not anymore now? Ref. CSS table column autowidth (there the table was also in fixed layout but thats back in 2011)

Here is the HTML and CSS:

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

td,
th {
  border: 1px solid #D5D5D5;
  padding: 15px;
}

.auto {
  width: 1px;
  white-space: nowrap;
}
<table cellspacing="0" cellpadding="0" border="0">
  <thead>
    <tr>
      <th>Column 1 even width</th>
      <th>Column 2 even width</th>
      <th>Column 3 even width</th>
      <th class="auto">Auto</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data 1</td>
      <td>Data 2</td>
      <td>Data 3</td>
      <td class="auto">Data4</td>
    </tr>
  </tbody>
</table>

I also have an example setup in the following jsfiddle:

http://jsfiddle.net/hCkch/21/

How do you make the last column auto width based on the content while the other columns respect table-layout: fixed?

Note: the three columns given above is just an example. So please no hardcoded answers to make each column width 100/3%. This is a general question and the answer should fit for n columns with even width but the last one auto width based on the content.

Niveditha Karmegam
  • 742
  • 11
  • 28
user1589188
  • 5,316
  • 17
  • 67
  • 130

2 Answers2

2

With table-layout, you will want to set the widths of the cells in the first row of the table (https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout). You'll also want to add a width of 100% for the final column that is meant to auto-expand. Here is an edit of your jsfiddle: http://jsfiddle.net/jessbodie/hCkch/31/

<table cellspacing="0" cellpadding="0" border="0">
  <thead>
    <tr>
      <th class="col1st">Column 1 even width</th>
      <th class="col2nd">Column 2 even width</th>
      <th class="col3rd">Column 3 even width</th>
      <th class="auto">Auto</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data 1</td>
      <td>Data 2</td>
      <td>Data 3</td>
      <td class="auto">Data4</td>
    </tr>
  </tbody>
</table>

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

td, th {
  border: 1px solid red;
  padding: 15px;
}

.col1st {
  width: 100px;
}

.col2nd {
  width: 100px;
}

.col3rd {
  width: 100px;
}

.auto {
  width: 100%;
  white-space: nowrap;
}

For making the first n columns the same width, in SASS you can use the calc function to come up with the widths.

Jess
  • 21
  • 3
  • Thanks, but if I have already hardcoded (or SASS calculated) the width of every other columns, whats the point of using `table-layout: fixed`? – user1589188 Jan 29 '18 at 23:13
  • Performance. According to MDN: "Under the "fixed" layout method, the entire table can be rendered once the first table row has been downloaded and analyzed. This can speed up rendering time over the "automatic" layout method" [MDN on Table Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout) – Jess Jan 30 '18 at 02:36
1

As mentioned in the comments, the only way I know to do this that should work cross browser is to get rid of table-layout: fixed; and set the width of the remaining columns. Fixed layouts are good for lots of things but automatically calculating based on content doesn't seem to be one of them.

table {
  width: 100%;
}

td, th {
  border: 1px solid #D5D5D5;
  padding: 15px;
  width: 33.33%
}

.auto {
  white-space: nowrap;
}
<table cellspacing="0" cellpadding="0" border="0">
  <thead>
    <tr>
      <th>Column 1 even width</th>
      <th>Column 2</th>
      <th>Column 3</th>
      <th class="auto">Auto</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data 1</td>
      <td>Data 2</td>
      <td>Data 3</td>
      <td>Data4</td>
    </tr>
  </tbody>
</table>

I realize you clarified that you don't want markup specific rules, but it does in fact accomplish your goal with the one requirement that you know how many columns you will be dealing with beforehand. In general, this should not be prohibitive.

Another possibly work around is to assign the widths client side using js after the fact:

$(document).ready(function() {
  var width = 100 / $('table tr:first th:not(.auto)').length;
  var cols = $('table th:not(.auto)');
  cols.css('width', width + '%');
});
table {
  width: 100%;
}

td, th {
  border: 1px solid #D5D5D5;
  padding: 15px;
}

.auto {
  white-space: nowrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table cellspacing="0" cellpadding="0" border="0">
  <thead>
    <tr>
      <th>Column 1 even width</th>
      <th>Column 2</th>
      <th>Column 3</th>
      <th class="auto">Auto</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data 1</td>
      <td>Data 2</td>
      <td>Data 3</td>
      <td>Data4</td>
    </tr>
  </tbody>
</table>

And finally, I'll mention there is a Firefox specific implementation of min-content that actually does exactly what you want. Unfortunately, it only works on Firefox:

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

td, th {
  border: 1px solid #D5D5D5;
  padding: 15px;
}

.auto {
  width: -moz-min-content;
  white-space: nowrap;
}
<table cellspacing="0" cellpadding="0" border="0">
  <thead>
    <tr>
      <th>Column 1 even width</th>
      <th>Column 2</th>
      <th>Column 3</th>
      <th class="auto">Auto</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data 1</td>
      <td>Data 2</td>
      <td>Data 3</td>
      <td>Data4</td>
    </tr>
  </tbody>
</table>
  • Thanks for the detailed examples. I still hope for a non-programmatic solution like the firefox one you have here without resorting to js. I will wait for another answer and see if there are others in the know who can share that trick. – user1589188 Jan 29 '18 at 05:38