162

Consider the following example: (live demo here)

$(function() {
  console.log("width = " + $("td").width());
});
td {
  border: 1px solid black;
  width: 50px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
  <tbody>
    <tr>
      <td>Hello Stack Overflow</td>
    </tr>
  </tbody>
</table>

The output is: width = 139, and the ellipsis doesn't appear.

What am I missing here?

ThS
  • 4,597
  • 2
  • 15
  • 27
Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746

12 Answers12

108

Apparently, adding:

td {
  display: block; /* or inline-block */
}

solves the problem as well.


Another possible solution is to set table-layout: fixed; for the table, and also set it's width. For example: http://jsfiddle.net/fd3Zx/5/

Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746
  • 4
    Exactly. Elements with `display: table-cell` (the default for `td` elements) don't accept a width. – Michael Mior Apr 29 '12 at 13:29
  • 30
    `display: block;` sort of defeats the purpose of using a table. I like the `table-layout: fixed;` option, it worked well for me. – Alex K Dec 13 '13 at 23:18
  • 12
    `table-layout:fixed` distributes the width of the columns in a less smart way. Is there another option that will assign column width the same way `table-layout: normal` and yet display the ellipsis correctly? – nest Jan 14 '15 at 08:34
  • This screws with the table border; using max-width does not. – Charlie Aug 26 '19 at 05:04
93

It's also important to put

table-layout:fixed;

Onto the containing table, so it operates well in IE9 (if your utilize max-width) as well.

streetlight
  • 5,968
  • 13
  • 62
  • 101
  • 7
    this will also make sure that text overflow works in responsive layouts – jao Oct 16 '13 at 16:30
  • 3
    This is exactly what I needed. I have the table width 100%. And all of the columns except for one with a fixed width. This allows the last column to take up as much space as is left over. – matthew_360 Nov 04 '14 at 18:48
85

As said before, you can use td { display: block; } but this defeats the purpose of using a table.

You can use table { table-layout: fixed; } but maybe you want it to behave differently for some colums.

So the best way to achieve what you want would be to wrap your text in a <div> and apply your CSS to the <div> (not to the <td>) like this :

td {
  border: 1px solid black;
}
td > div {
  width: 50px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
Hendy Irawan
  • 20,498
  • 11
  • 103
  • 114
marcosbdm
  • 1,002
  • 8
  • 8
  • 2
    This is the simplest method I've seen and it actually works in IE8. – Keith Ketterer Mar 04 '15 at 19:04
  • 2
    THAT is actually the best solution I've seen on ellipsis in tables. – membersound Feb 11 '16 at 14:30
  • 5
    I'm not clear on how this is any different, since it forces the definition of a width. It still completely disables table column auto-sizing, which means you now have to fiddle with pixel nudging on every column in your entire app. For a large app this is a nightmare. – Dave Munger Oct 30 '20 at 15:47
46

Try using max-width instead of width, the table will still calculate the width automatically.

Works even in ie11 (with ie8 compatibility mode).

td.max-width-50 {
  border: 1px solid black;
  max-width: 50px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<table>
  <tbody>
    <tr>
      <td class="max-width-50">Hello Stack Overflow</td>
    </tr>
    <tr>
      <td>Hello Stack Overflow</td>
    </tr>
    <tr>
      <td>Hello Stack Overflow</td>
    </tr>
  </tbody>
</table>

jsfiddle.

Muhammad Omer Aslam
  • 22,976
  • 9
  • 42
  • 68
Asherah
  • 18,948
  • 5
  • 53
  • 72
  • 1
    Well spotted. It is probably best to use *both*, so that the element is a fixed width. Otherwise it could be shorter if the contents allowed it. – LSerni Aug 31 '15 at 10:38
  • Way better than display hack; displayhack screws with the table border. – Charlie Aug 26 '19 at 05:03
27

Demo page

For tables with dynamic width, I found the below way to produce satisfying results. Each <th> which is wished to have trimmed-text ability should have an inner wrapping element which wraps the contents of the <th> allow text-overflow to work.

The real trick is to set max-width (on the <th>) in vw units.

This will effectively cause the element's width to be "bound" to the viewport width (browser window) and will result in a responsive content clipping. Set the vw units to a satisfying value needed.

Minimal CSS:

th{ max-width:10vw; }
      
th > .wrap{ 
   text-overflow:ellipsis;
   overflow:hidden;
   white-space:nowrap;
}

Demo (with editable texts):

document.designMode="on"
table {
  font: 18px Arial;
  width: 40%;
  margin: 1em auto;
  color: #333;
  border: 1px solid rgba(153, 153, 153, 0.4);
}

table td, table th {
  text-align: left;
  padding: 1.2em 20px;
  white-space: nowrap;
  border-left: 1px solid rgba(153, 153, 153, 0.4);
}

table td:first-child, table th:first-child {
  border-left: 0;
}

table th {
  border-bottom: 1px solid rgba(153, 153, 153, 0.4);
  font-weight: 400;
  text-transform: uppercase;
  max-width: 10vw;
}

table th > .wrap {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
<table>
    <thead>
        <tr>
            <th>
                <div class="wrap" title="Some long title">Some long title</div>
            </th>
            <th>
                <div class="wrap">Short</div>
            </th>
            <th>
                <div class="wrap">medium one</div>
            </th>
            <th>
                <div class="wrap" title="endlessly super long title which no developer likes to see">endlessly super long title which no developer likes to see</div>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>-</td>
            <td>-</td>
            <td>-</td>
            <td>very long text here</td>
        </tr>
    </tbody>
</table>
vsync
  • 118,978
  • 58
  • 307
  • 400
  • Not sure how this ``vw`` unit works, but the result is just perfect, because the table keeps auto-sizing columns normally with this method. – andreszs Feb 08 '22 at 22:57
3

Just offering an alternative as I had this problem and none of the other answers here had the desired effect I wanted. So instead I used a list. Now semantically the information I was outputting could have been regarded as both tabular data but also listed data.

So in the end what I did was:

<ul>
    <li class="group">
        <span class="title">...</span>
        <span class="description">...</span>
        <span class="mp3-player">...</span>
        <span class="download">...</span>
        <span class="shortlist">...</span>
    </li>
    <!-- looped <li> -->
</ul>

So basically ul is table, li is tr, and span is td.

Then in CSS I set the span elements to be display:block; and float:left; (I prefer that combination to inline-block as it'll work in older versions of IE, to clear the float effect see: http://css-tricks.com/snippets/css/clear-fix/) and to also have the ellipses:

span {
    display: block;
    float: left;
    width: 100%;

    // truncate when long
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

Then all you do is set the max-widths of your spans and that'll give the list an appearance of a table.

diggersworld
  • 12,770
  • 24
  • 84
  • 119
2

Instead of using ellipsis to solve the problem of overflowing text, I found that a disabled and styled input looked better and still allows the user to view and select the entire string if they need to.

<input disabled='disabled' style="border: 0; padding: 0; margin: 0" />

It looks like a text field but is highlight-able so more user friendly

craig
  • 285
  • 2
  • 10
  • 2
    It is not user friendly because using assistive tecnologies this gets mis-read as an input and so the user thinks he can input something. It is quite not ok to misuse the semantics of the elements. – Carlo Sep 12 '17 at 09:36
  • OMG, this is so clever! since it is part of the table, just simply set the input as borderless with transparent background. I love this solution! – Sam Jun 25 '20 at 03:58
1

Check box-sizing css property of your td elements. I had problem with css template which sets it to border-box value. You need set box-sizing: content-box.

dippas
  • 58,591
  • 15
  • 114
  • 126
David Slavík
  • 1,132
  • 1
  • 14
  • 23
1

I've tried many of the above solutions but none of them felt flexible or satisfying.

This little hack with max-width: 1px can be applied directly to the td element

.truncated-cell {
   max-width: 1px;
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
 }
J.Kirk.
  • 943
  • 3
  • 12
  • 32
  • This seems to do the same exact thing as setting the table to fixed-width, which is that it forces all columns to an equal width rather than providing the benefit of a table's auto-width capabilities. That leaves us having to manually set widths on every single table in an application, which is tedious and error-prone. – Dave Munger Oct 30 '20 at 15:43
0

Leave your tables as they are. Just wrap the content inside the TD's with a span that has the truncation CSS applied.

/* CSS */
.truncate {
    width: 50px; /*your fixed width */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: block; /* this fixes your issue */
}

<!-- HTML -->
<table>
    <tbody>
        <tr>
            <td>
                <span class="truncate">
                    Table data to be truncated if it's too long.
                </span>
            </td>
        </tr>
    </tbody>
</table>
Jeff Sieffert
  • 109
  • 1
  • 7
0
.ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
}

The above setting worked for me, without changing table widths. I added a div inside and added the class ellipsis to it.

-2

If you don't want to set max-width to td (like in this answer), you can set max-width to div:

function so_hack(){}

function so_hack(){} http://jsfiddle.net/fd3Zx/754/ function so_hack(){}

function so_hack(){}

Note: 100% doesn't work, but 99% does the trick in FF. Other modern browsers doesn't need silly div hacks.

td {
  border: 1px solid black;
    padding-left:5px;
    padding-right:5px;
}
td>div{
    max-width: 99%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

}
Community
  • 1
  • 1
Timo Kähkönen
  • 11,962
  • 9
  • 71
  • 112