Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimal auto width for table columns

Tags:

html

css

I'm creating a table to inspect tabular data (like result of SQL query) and trying to find the optimal layout.

I don't know the number columns or its content, I know only that some columns could be narrow and some wide. And that table should take no more than 100% of its container and columns should not wrap, it's ok to hide overflow. And it should utilise the available space in a reasonable way.

How it could be done? I tried table-layout: fixed (without it table won't respect width: 100% and takes wider space) but the layout din't utilise all the available space (see screenshot below). Are there better ways? Maybe involving some JS calculations (I'm using Svelte)?

enter image description here

One possible improvement would be - if the column is narrow, let it be narrow. But in the example below the narrow column "Aaa" still take the extra space it don't need.

Example:

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

table td {
  white-space:   nowrap;
}

table td {
  overflow:      hidden;
  text-overflow: ellipsis;
}
<html>
<body>

<table>
  <tr>
    <td>Aaa</td>
    <td>Bbb bbb bbb bbb bb bbbbbb bb bbbbbb bb bbbbbb bbbbbbbb bb  bbbbbb bb  bbbbbb bb bbbbbb bb</td>
    <td>Ccc cc c ccccc c cccc</td>
  </tr>

</table>

</body>
</html>

P.S.

Please note the white-space: nowrap; - the solution for the similar question Table overflowing outside of div doesn't work with the white-space: nowrap; option.

like image 864
Alex Craft Avatar asked Nov 23 '25 11:11

Alex Craft


1 Answers

You'll need a little JavaScript to have a fixed table at 100% with truncated content and no overflow. table-layout: fixed is useless unless you explicitly set column widths and since the number of columns are variable as well as length of cell content, the most efficient way to handle it is by ensuring each column is of equal width.

  1. Use the table rows cells collection properties to get the number of <td> in a <tr>
const numberOfColumns = table.rows[0].cells.length;
  1. Then divide 100 by the number of columns
let columnWidth = `${100 / numberOfColumns}%`;
  1. Apply that number as a percentage width to each <td> of the first <tr>
[...table.rows[0].cells].forEach(td => td.style = columnWidth);

Note: The first example does not adjust for empty cells because it's pointless when you have more than one row. Example 2 is added to show how to adjust for empty cells (not recommended for tables with multiple rows). Basically it assigns 1% width to each column then assigns the following percentage width to each <td> that has text (keeps track by index number):

arrayOfIndices.forEach(index => table.rows[0].cells[index].style.width = `${(100 - numberOfEmpty)/arrayOfIndices.length}%`);

Example 1

const table = document.querySelector('table');
const columns = table.rows[0].cells.length;
[...table.rows[0].cells].forEach(td => td.style = `${100/columns}%`);
table {
  width: 100%;
  table-layout: fixed;
}

td {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
<main>
  <table>
    <tr>
      <td>xxxxxxxxxxxx</td>
      <td>xxxxxxxxxxxx</td>
      <td>xxxxxxxxxxxx</td>
      <td>xxxxxxxxxxxx</td>
      <td>xxxxxxxxxxxx</td>
      <td>xxxxxxxxxxxx</td>
      <td>xxxxxxxxxxxx</td>
      <td>xxxxxxxxxxxx</td>
    </tr>
  </table>
</main>

Note: <td>s have an alternating background color. The empty cells are at 1% width (2nd and 5th cells).

Example 2

const table = document.querySelector('table');
const columns = table.rows[0].cells.length;
const fullCells = [...table.rows[0].cells].flatMap((td, idx) => td.textContent.length > 0 ? [idx] : []); 
const newWidth = 100 - (columns - fullCells.length);
[...table.rows[0].cells].forEach(td => td.style.width = '1%');
fullCells.forEach(index => table.rows[0].cells[index].style.width = `${newWidth/fullCells.length}%`);
table {
  width: 100%;
  table-layout: fixed;
}

td {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

td:nth-child(odd) {
  background: tomato;
}

td:nth-child(even) {
  background: cyan;
}
<main>
  <table>
    <tr>
      <td>AAAAAAAAAAAA</td>
      <td></td>
      <td>CCCCCCCCCCCCCCCCCCCCCCCCCCCC</td>
      <td>DDDDDDDDDDDDDDDDDDDDDDDDDDDD</td>
      <td></td>
      <td>FFFFFFFFFFFF</td>
      <td>GGGGGGGGGGGG</td>
      <td>HHHHHHHHHHHH</td>
    </tr>
  </table>
</main>
like image 94
zer00ne Avatar answered Nov 26 '25 03:11

zer00ne



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!