Automatic column width with `overflow-wrap: break-word`

Viewed 618

I have an HTML table with 3 columns - ID, timestamp, and data. ID and timestamp are quite narrow, and data can be really big, sometimes it has no line breaks so to avoid horizontal scrollbars I set overflow-wrap: break-word. To make it work, I need to set my table-layout to fixed.

While it works, I don't like that all columns have now equal width. I can set the first two column sizes to some fixed width, but I'd like them to fit content. How can I force the 2 first columns to adjust their width and the third one to take the remaining space?

Here's my code sample:

<table style="width: 100%; table-layout: fixed; overflow-wrap: break-word">
  <tr>
    <th>ID</th>
    <th>Time</th>
    <th>Data</th>
  </tr>
  <tr>
    <td>0</td>
    <td>10:11</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space</td>
  </tr>
  <tr>
    <td>1</td>
    <td>10:12</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space</td>
  </tr>
  <tr>
    <td>2</td>
    <td>10:13</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space_and_it_may_be_so_long_that_it_wont_fit_into_the_column_and_needs_to_be_wrapped</td>
  </tr>
</table>

Basically what I need is to somehow force the 2 first columns to ignore the table-layout: fixed or to force overflow-wrap: break-word work without it.

4 Answers

I think either you should go with display flex or add a small tweak in the CSS like shown below.

.table-wrap tr > td:nth-child(1),
.table-wrap tr > td:nth-child(2) {
  white-space: nowrap;
}

.table-wrap tr > td:nth-child(3) {
  word-break: break-word;
}

th,td {
  padding: 0px 16px
}
<table class="table-wrap" style="width: 100%;">
  <tr>
    <th>ID</th>
    <th>Time</th>
    <th>Data</th>
  </tr>
  <tr>
    <td>0</td>
    <td>10:11</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space</td>
  </tr>
  <tr>
    <td>1</td>
    <td>10:12</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space</td>
  </tr>
  <tr>
    <td>2</td>
    <td>10:13</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space_and_it_may_be_so_long_that_it_wont_fit_into_the_column_and_needs_to_be_wrapped</td>
  </tr>
</table>

You could just use max-width for the table. Then you just assign the word-break: break-word; to your third <td>. Hope this was what you wanted to achive.

table {
  max-width: 100%;
}

td {
  vertical-align: top;
}

th {
text-align: left;
}

td:nth-child(3){
    word-break: break-word;
}
<table>
  <tr>
    <th>ID</th>
    <th>Time</th>
    <th>Data</th>
  </tr>
  <tr>
    <td>0</td>
    <td>10:11</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space</td>
  </tr>
  <tr>
    <td>1</td>
    <td>10:12</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space</td>
  </tr>
  <tr>
    <td>2</td>
    <td>10:13</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space_and_it_may_be_so_long_that_it_wont_fit_into_the_column_and_needs_to_be_wrapped</td>
  </tr>
</table>

try to add display: flex to your table like this:

table {
    width: 100%;
    display: flex;
}

td, th {
    padding: 5px 10px;
    vertical-align: top;
    text-align: left;
    white-space: nowrap;
}
td:nth-child(3){
    word-break: break-word;
    white-space: break-spaces;
}

table {
    width: 100%;
    display: flex;
}

td, th {
    padding: 5px 10px;
    vertical-align: top;
    text-align: left;
    white-space: nowrap;
}
td:nth-child(3){
    word-break: break-word;
    white-space: break-spaces;
}
<table style="width: 100%; table-layout: fixed; overflow-wrap: break-word">
  <tr>
    <th>ID</th>
    <th>Time</th>
    <th>Data</th>
  </tr>
  <tr>
    <td>0</td>
    <td>10:11</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space</td>
  </tr>
  <tr>
    <td>1</td>
    <td>10:12</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space</td>
  </tr>
  <tr>
    <td>2</td>
    <td>10:13</td>
    <td>some_long_value_that_may_or_may_not_contain_a_space_and_it_may_be_so_long_that_it_wont_fit_into_the_column_and_needs_to_be_wrapped</td>
  </tr>
</table>

If you want the css to ignore specific selector, you can use the :not() pseudo

td:not(td:nth-child(1), td:nth-child(2)){
    // css to be applied just on the 3rd col
}

or in your case, remove the width:100% from the table

table {
    width: 100%;
}

td, th {
    vertical-align: top;
    text-align: left;
    padding: 5px 10px;
}

td:not(td:nth-child(1), td:nth-child(2)){
    overflow-wrap: anywhere;
}
Related