Incorrect percentage "padded" columns width when the table-layout is fixed

Viewed 169

I'm trying to use percentage columns (that have some paddings) with the table-layout fixed. When I do that for regular divs, everything works as expected (box-sizing in divs is content-box). All paddings are subtracted from 500px, then the rest is split in a half, so div's widths are 150px;

<div style="display:flex;flex-direction:row;width:500px">
    <div style="width:50%;padding:0px">ADSD</div>
    <div style="width:50%;padding:0px 100px">SADDS</div>
</div>

But when I do the same for a table everything works different:

<table style="width:500px;table-layout:fixed">
  <tr>
    <td style="width:50%;padding:0px">ADSD</td>
    <td style="width:50%;padding:0px 100px">SADDS</td>
  </tr>
</table>

Cells get pretty odd widths (175.812 vs 118.188). It seems that paddings are considered, but god knows how. So the question is: how are paddings are considered for percentage columns when the table layout is fixed?

There was a question about table paddings before, but it was about the table padding itself, and not its cells paddings (so it's not relevant, border-spacing doesn't help, etc.)

2 Answers

*{box-sizing:border-box} That's all you need my friend. Elements don't bound to their box. We need to give them box-sizing css for to behave properly. I hope this helps.

*{box-sizing:border-box}
Flex
<div style="display:flex;flex-direction:row;width:500px">
    <div style="width:50%;padding:0px">ADSD</div>
    <div style="width:50%;padding:0px 100px">SADDS</div>
</div>

<br>
Table
<table style="width:500px;table-layout:fixed">
  <tr>
    <td style="width:50%;padding:0px">ADSD</td>
    <td style="width:50%;padding:0px 100px">SADDS</td>
  </tr>
</table>

My whole answer was based on results obtained on Firefox 102.0 for Windows. It was found out later that given the same code, the result it's different on Chrome for example. So my answer doesn't tell the whole story.

And here a github issue with a detailed conversation and headaches around the table-layout:fixed feature. But it seems to me that the rules are vague enough for each vendor to interpret a given edge case in a different way. Anyway details like those found in that link, may help reading out why the sizes were computed differently in a different browser.


The table has a fixed width given as width:500px; and the width of the available space for the two columns get calculated as fullWidth - padding because appearently it first takes into account the fixed sizes. I actually don't have a clear reference for such statement, but it just comes out from trying. Reading around I found out it's raccomended not to use % width for columns when having table-layout: fixed; but that's another story.

The question remains: how the width values get calculated in this scenario?

Since the padding: 0px 100px gets exploded in padding-left: 100px; padding-right: 100px; the size of the available width for columns content is:

500px - 100px - 100px = 300px

The width of each column gets calculated as 50% of that amount:

50% of 300px ~= 150px

Here's a demo showing off the width of the elements once rendered:

const table = document.querySelector('.table');
const firstColumn = document.querySelector('.table tr > td:nth-child(1)');
const secondColumn = document.querySelector('.table tr > td:nth-child(2)');
const secondColumnContent = secondColumn.querySelector('div');

console.log( 'Table width: ' + table.offsetWidth );
console.log( 'First Column width: ' + firstColumn.offsetWidth );
console.log( 'Second Column width: ' + secondColumn.offsetWidth );
console.log( 'Second Column width (no padding): ' + secondColumnContent.offsetWidth );
.table{
  width:500px;
  table-layout:fixed;  
  box-sizing: content-box;
  border-collapse: collapse;
}

.table tr > td:nth-child(1){
  width:50%;
  padding:0px;
  border: solid 1px green;
}

.table tr > td:nth-child(2){
  width:50%;
  padding:0px 100px;
  border:solid 1px gray;
}

.table tr > td:nth-child(2) > div{
  border:solid 1px blue;
  height:1rem;
}
<table class="table">
  <tr>
    <td>1stCOL</td>
    <td>
      <div>
        2ndCOL
      </div>
    </td>
  </tr>
</table>


And here how it shows on Firefox 102.0 on my screen:

Rendered on Firefox 102.0 on Windows 10

Compared to what happens on Chrome 103.0.5060.114:

enter image description here

Related