2

Setting max-width in a table cell to 250px will, paradoxically, prevent the cell (column) from getting smaller than 250px when the width of the table changes. At the same time, the maximum width does not seem to be constrained at all.

...why?

Fiddle:

See this in action: http://jsfiddle.net/cehjc8m6/1/

HTML:

<table>
<tr>
    <td>Left col</td>
    <td class="ell">
        This is a rather long text. It should be truncateed when it
        exceeds the available horizontal space.
    </td>
    <td>Right col</td>
</tr>
</table>

CSS:

table {
    width: 500px;  // change this value to see the effect
}
td {
    white-space: nowrap;
}
td.ell {
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 250px;
}
dippas
  • 58,591
  • 15
  • 114
  • 126
Zilk
  • 8,917
  • 7
  • 36
  • 44

5 Answers5

3

As others have noted, the behavior of max-width on table cells is not defined by the standard. That said, current* browsers all give the exact same counter-intuitive results, so there has to be a common algorithm to handle this case (at least for now).

* only the very newest version of MSIE/Edge (but what else is new...)

Looking at it more closely, the mention of minimum widths is misleading; max-width actually does limit the maximum width. So why is the observed width of the column larger than the specified value?

Because it is applied before the specified table width is taken into account.

In a table with only one row and two cells, one of which has max-width, overflow:hidden and text-overflow:ellipsis set, the column widths are calculated first without any restrictions on the total width. After that, the cells are stretched to the specified table width, keeping their proportions from the first calculation step.

This test page shows the effect with and without table width restrictions, and for various text content lengths: http://output.jsbin.com/hebixu

To get a more predictable result in tables with a set width, the other cells can be given an explicit width. Then again, if the optimal widths are known beforehand, we can just use table-layout:fixed.

Zilk
  • 8,917
  • 7
  • 36
  • 44
1

Try this:

td.ell {
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 250px;
    display: inline-block;
}

See here : http://jsfiddle.net/sachinkk/cehjc8m6/3/

var table = document.querySelector("table"),
    cell  = document.querySelector(".ell"),
    sizer = document.querySelector("input"),
    span  = document.querySelector("span");

sizer.addEventListener("wheel", wheelHandler, false);
updateWidthDisplay();

function wheelHandler (evt)
{
    var incr = evt.deltaY < 0 ? 10 : -10;
    table.style.width = (table.offsetWidth + incr) + "px";
    updateWidthDisplay();
}

function updateWidthDisplay ()
{
    sizer.value = table.offsetWidth + "px";
    span.textContent = cell.offsetWidth + "px";
}
body {
    font: normal 13px sans-serif;
}
table {
    width: 500px;
    border-collapse: collapse;
    background: gold;
}
td {
    white-space: nowrap;
}
td.ell {
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 250px;
    background: tomato;
    display: inline-block;
}
input {
    width: 50px;
}
em {
    color: #aaa;
    padding-left: 12px;
}
<table>
<tbody>
<tr>
    <td>Left col</td>
    <td class="ell">
        This is a rather long text. It should be truncated when it
        exceeds the available horizontal space.
    </td>
    <td>Right col</td>
</tr>
</tbody>
</table>

<p>
    table width: <input> <em>&larr; use mouse wheel to change</em><br>
    middle col width: <span></span>
Sachink
  • 1,425
  • 10
  • 22
  • `inline-block` makes them no longer table cells. Which means, among other things, that browsers can arrange such "cells" vertically, even if they are in the same row. – Zilk Jun 23 '15 at 10:18
1

in order to make max-width work in td ( if displayed as table-cell - as it is by default) you need to set the parent ( either table or a another element you wish displayed as table) as table-layout:fixed

see more info here

here is a snippet:

var table = document.querySelector("table"),
  cell = document.querySelector(".ell"),
  sizer = document.querySelector("input"),
  span = document.querySelector("span");

sizer.addEventListener("wheel", wheelHandler, false);
updateWidthDisplay();

function wheelHandler(evt) {
  var incr = evt.deltaY < 0 ? 10 : -10;
  table.style.width = (table.offsetWidth + incr) + "px";
  updateWidthDisplay();
}

function updateWidthDisplay() {
  sizer.value = table.offsetWidth + "px";
  span.textContent = cell.offsetWidth + "px";
}
body {
  font: normal 13px sans-serif;
}
table {
  width: 500px;
  border-collapse: collapse;
  background: gold;
  table-layout: fixed;
  /* HERE IS THE TRICK */
}
td {
  white-space: nowrap;
}
td.ell {
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 250px;
  background: tomato;
}
input {
  width: 50px;
}
em {
  color: #aaa;
  padding-left: 12px;
}
<table>
  <tbody>
    <tr>
      <td>Left col</td>
      <td class="ell">
        This is a rather long text. It should be truncated when it exceeds the available horizontal space.
      </td>
      <td>Right col</td>
    </tr>
  </tbody>
</table>

<p>
  table width:
  <input> <em>&larr; use mouse wheel to change</em>
  <br>middle col width: <span></span>
dippas
  • 58,591
  • 15
  • 114
  • 126
1

In CSS 2.1, the effect of 'min-width' and 'max-width' on tables, inline tables, table cells, table columns, and column groups is undefined.

See the specs - http://www.w3.org/TR/CSS21/visudet.html#min-max-widths

It may work in some cases, BUT you may not expect it to always work.

The width property should be used instead, and table-layout:fixed can be useful very often.

Stickers
  • 75,527
  • 23
  • 147
  • 186
  • See this updated [fiddle demo](http://jsfiddle.net/cehjc8m6/4/) if it is what you're trying to get. – Stickers Jun 19 '15 at 15:03
  • Thanks for the link to the CCS specs, that explains why `max-width` does not have to act as a max-width for `td` elements. Why all current major browsers agree to have it act like a *minimum width*, on the other hand... – Zilk Jun 23 '15 at 11:36
  • In the updated fiddle, the middle column now always has a fixed width of 250px. It's true that the overflowing text is truncated without resorting to `max-width`, but the layout is rigid. Still, it gives me something to work with. – Zilk Jun 23 '15 at 13:13
  • @Zilk just guessing, I wondered if you want it to like [this demo](http://jsfiddle.net/cehjc8m6/5/)? – Stickers Jun 23 '15 at 13:51
  • Yes, exactly. This works pretty much like my original fiddle, except it avoids the undefined behavior of max-width on `td`s. Also like the original fiddle, there is no way to limit the width (of the actual outer table cell, in this case). It's an interesting structure, although I would hesitate to use this for a table with ~1k rows, because that would create ~1k additional mini-tables... – Zilk Jun 23 '15 at 14:29
  • @Zilk you'd better avoid the 2nd demo if you have a large set of data, and stick with table-layout:fixed on main table - [for speed up rendering](http://jsfiddle.net/kjpczL5w/2/). – Stickers Jun 23 '15 at 14:33
0

I've got a really simple solution to this...

I've had exactly the same issue with width and max-width but found sometimes that adding things like the overflow attributes mentioned in other responses didn't help.

The problem was specifying values using pixels as the unit of measurement.

To give an example; I had a table column I had that I never wanted to be more than the width of the icons that I was displaying in them, which were around 80x80 pixels.

In the end I found that simply specifying a very small percentage width worked. The percentage I chose was likely always going to be smaller than what I wanted, however the fact that the cell contained an image meant that it stretched to the minimum I needed to fit the image.

AdamJones
  • 652
  • 1
  • 15
  • 38