648

I want to use CSS text-overflow in a table cell, such that if the text is too long to fit on one line, it will clip with an ellipsis instead of wrapping to multiple lines. Is this possible?

I tried this:

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

But the white-space: nowrap seems to make the text (and its cell) continually expand out to the right, pushing the total width of the table beyond the width of its container. Without it, however, the text continues to wrap to multiple lines when it hits the edge of the cell.

Kara
  • 6,115
  • 16
  • 50
  • 57
daGUY
  • 27,055
  • 29
  • 75
  • 119

14 Answers14

1153

To clip text with an ellipsis when it overflows a table cell, you will need to set the max-width CSS property on each td class for the overflow to work. No extra layout div elements are required:

td
{
 max-width: 100px;
 overflow: hidden;
 text-overflow: ellipsis;
 white-space: nowrap;
}

For responsive layouts; use the max-width CSS property to specify the effective minimum width of the column, or just use max-width: 0; for unlimited flexibility. Also, the containing table will need a specific width, typically width: 100%;, and the columns will typically have their width set as percentage of the total width

table {width: 100%;}
td
{
 max-width: 0;
 overflow: hidden;
 text-overflow: ellipsis;
 white-space: nowrap;
}
td.column_a {width: 30%;}
td.column_b {width: 70%;}

Historical: For IE 9 (or less) you need to have this in your HTML, to fix an IE-specific rendering issue

<!--[if IE]>
<style>
table {table-layout: fixed; width: 100px;}
</style>
<![endif]-->
John
  • 1
  • 13
  • 98
  • 177
TFD
  • 23,890
  • 2
  • 34
  • 51
  • 7
    The table also needs a width for this to work in IE. http://jsfiddle.net/rBthS/69 – Trevor Dixon Aug 30 '12 at 22:46
  • @Trevor Dixon Thanks Trev, didn't notice that was a requirement, but is in my normal code anyway – TFD Aug 30 '12 at 23:10
  • @TFD about the IE issue, could you provide a reading link? Or explain a bit what's going on please – Olga Nov 18 '13 at 09:56
  • @Olga Old IE generally renders different from other render engines. It seems to need width property, regardless of max-width property – TFD Nov 18 '13 at 10:18
  • Also consider wrapping the contents inside the TD with a DIV tag and then apply the text flow limiting css to that DIV, this gave me the functionality I needed. – i_a Feb 08 '14 at 16:24
  • 3
    If you set `width: 100%;` and `min-width: 1px;` the cell will always be as wide as possible and will only use ellipsis to truncate the text when it needs to (not when the element width hits a certain size) - this is very useful for responsive layouts. – Duncan Walker Jun 27 '14 at 17:15
  • 3
    @OzrenTkalcecKrznaric it works on `display: table-cell` indeed, but not when the `max-width` is defined in percentage (%). Tested on FF 32 – Greg Sep 04 '14 at 00:42
  • 21
    (Following up on the above) in the case you use % values, then only using `table-layout: fixed` on the element with `display: table` will do the trick – Greg Sep 04 '14 at 00:53
  • 1
    To expand a little on the `` responsive case: remove `width: 100%`s from all cells or columns, add `table-layout: fixed; width: 100%` to the **** element, then specify widths *only* to `` or (first row) `
    ` elements you want to be *no wider* than that width. Have no width specified for columns that should be as wide as possible.
    – user56reinstatemonica8 Sep 15 '14 at 11:29
  • 1
    How about if you want the width of the columns to be assigned automatically on a responsive fashion like bootstrap responsive table? setting a max-width will intrude on that. Is there a workaround? – nest Jan 14 '15 at 08:32
  • Check out http://stackoverflow.com/questions/17345158/variable-sized-column-with-ellipsis-in-a-table can reduce max-width to 1px. – gamliela Mar 19 '15 at 14:46
  • thanks a ton.. it worked like magic. I was just missing max-width:0; – anuj arora Dec 01 '16 at 21:17
  • Works perfectly as of January 2020 and latest version of Chrome etc. – Mike Upjohn Jan 29 '20 at 15:11
  • Using fixed layout kinda goes against using tables in the first place (plain divs or flex work just fine in that case), the answer by Olaf works while preserving fluid table behaviors and automatic width. – Eric Grange Aug 27 '20 at 05:44
  • 3
    ATTENTION - max-width: 0; stopped working on 27-05-2021 with Chrome Version 91.0.4472.77 – Vlad Teodor May 27 '21 at 16:32
  • For variable width columns, you'd need to do something like this: https://www.geeksforgeeks.org/how-to-use-text-overflow-in-a-table-cell/ – thdoan May 28 '23 at 01:35
127

Specifying a max-width or fixed width doesn't work for all situations, and the table should be fluid and auto-space its cells. That's what tables are for. Works on IE9 and other browsers.

Use this: http://jsfiddle.net/maruxa1j/

table {
    width: 100%;
}
.first {
    width: 50%;
}
.ellipsis {
    position: relative;
}
.ellipsis:before {
    content: '&nbsp;';
    visibility: hidden;
}
.ellipsis span {
    position: absolute;
    left: 0;
    right: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
<table border="1">
    <thead>
        <tr>
            <th>Header 1</th>
            <th>Header 2</th>
            <th>Header 3</th>
            <th>Header 4</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td class="ellipsis first"><span>This Text Overflows and is too large for its cell.</span></td>
            <td class="ellipsis"><span>This Text Overflows and is too large for its cell.</span></td>
            <td class="ellipsis"><span>This Text Overflows and is too large for its cell.</span></td>
            <td class="ellipsis"><span>This Text Overflows and is too large for its cell.</span></td>
        </tr>
    </tbody>
</table>
anthumchris
  • 8,245
  • 2
  • 28
  • 53
  • 1
    Note: this solution wraps cell contents in `` elements. – Roy Tinker Jul 02 '15 at 16:58
  • 3
    This is a really clever solution, and works well for all the tables I would require a solution for. It does however require you to set widths if you don't want all the table cells to be the same width. – Kevin Beal Nov 05 '15 at 21:44
  • 1
    When there are no fixed widths, this solution works best. Very clever indeed! – avidenic Jun 16 '16 at 09:22
  • 1
    This keeps the vertical alignment when other solution like `display: block` did not – j3ff Apr 10 '18 at 18:03
  • "table should be fluid and auto-space its cells. That's what tables are for.". Really? Where is this rule from? – Simon Kagwi Feb 27 '20 at 20:58
  • what is this `:before` used for? I tried to remove it and didn't notice any change, browser compatibility maybe? – gogaz Apr 08 '20 at 18:25
  • This trick works well with `span:hover` effect to popup the full text. Just add some border, background, and let the text wrap out of the cell (`white-space: normal`). – Josef Kufner Sep 07 '20 at 11:18
  • 2
    @gogaz The `:before` sets height of the cell so that it does not collapse when there is no other cell around. Also, some borders may not be rendered for empty cells. – Josef Kufner Sep 07 '20 at 11:19
  • 2
    HTML entities like ` ` [don't work](https://stackoverflow.com/questions/190396/adding-html-entities-using-css-content) in CSS `content` property values. – Ghost4Man Sep 22 '20 at 08:37
  • 1
    I must be missing something, although I followed this css exactly and while it does make truncating with the ellipsis work, it definitely does NOT autosize the columns (at least, not in Chrome). They still wind up being forced to equal width, so this is effectively the exact same solution as setting the table to fixed-width, only with lots more CSS. – Dave Munger Oct 30 '20 at 16:38
  • 1
    So, to follow up, I took a look at the fiddle and there it DOES set a width (though a percentage width) on the column that gets truncated. So, "the table should be fluid and auto-space its cells" is a bit misleading imho. – Dave Munger Oct 30 '20 at 16:41
  • The dots are not appearing with this solution, how come? – Floris Feb 11 '21 at 12:21
  • @floris click _Run Code Snippet_ above – anthumchris Feb 11 '21 at 20:10
  • 1
    That's an amazing solution. But I'd replace `...` by `
    ...`. Otherwise the cell padding is not respected.
    – Cequiel Mar 02 '21 at 08:22
48

Why does this happen?

It seems this section on w3.org suggests that text-overflow applies only to block elements:

11.1.  Overflow Ellipsis: the ‘text-overflow’ property

text-overflow      clip | ellipsis | <string>  
Initial:           clip   
APPLIES TO:        BLOCK CONTAINERS               <<<<
Inherited:         no  
Percentages:       N/A  
Media:             visual  
Computed value:    as specified  

The MDN says the same.

This jsfiddle has your code (with a few debug modifications), which works fine if it's applied to a div instead of a td. It also has the only workaround I could quickly think of, by wrapping the contents of the td in a containing div block. However, that looks like "ugly" markup to me, so I'm hoping someone else has a better solution. The code to test this looks like this:

td, div {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: 1px solid red;
  width: 80px;
}
Works, but no tables anymore:
<div>Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah.</div>

Works, but non-semantic markup required:
<table><tr><td><div>Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah.</div></td></tr></table>
Jeroen
  • 60,696
  • 40
  • 206
  • 339
  • 2
    Nice, thanks. I couldn't remove the table cells from my markup, so instead I just wrapped the contents in divs (with their widths set to the widths of the cells) and applied the overflow there instead. Worked like a charm! – daGUY Mar 20 '12 at 16:14
37

In case you don't want to set fixed width to anything

The solution below allows you to have table cell content that is long, but must not affect the width of the parent table, nor the height of the parent row. For example where you want to have a table with width:100% that still applies auto-size feature to all other cells. Useful in data grids with "Notes" or "Comment" column or something.

enter image description here

Add these 3 rules to your CSS:

.text-overflow-dynamic-container {
    position: relative;
    max-width: 100%;
    padding: 0 !important;
    display: -webkit-flex;
    display: -moz-flex;
    display: flex;
    vertical-align: text-bottom !important;
}
.text-overflow-dynamic-ellipsis {
    position: absolute;
    white-space: nowrap;
    overflow-y: visible;
    overflow-x: hidden;
    text-overflow: ellipsis;
    -ms-text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    max-width: 100%;
    min-width: 0;
    width:100%;
    top: 0;
    left: 0;
}
.text-overflow-dynamic-container:after,
.text-overflow-dynamic-ellipsis:after {
    content: '-';
    display: inline;
    visibility: hidden;
    width: 0;
}

Format HTML like this in any table cell you want dynamic text overflow:

<td>
  <span class="text-overflow-dynamic-container">
    <span class="text-overflow-dynamic-ellipsis" title="...your text again for usability...">
      //...your long text here...
    </span>
  </span>
</td>

Additionally apply desired min-width (or none at all) to the table cell.

Of course the fiddle: https://jsfiddle.net/9wycg99v/23/

Slava
  • 2,887
  • 3
  • 30
  • 39
  • It messes up the selected width limits of every column, e.g. if you have some columns defined for `max-width: X` they now can be wider -- I thought this is because of `display: flex` being used, but I removed that and see no difference... – user9645 Feb 02 '18 at 13:21
34

If you just want the table to auto-layout

Without using max-width, or percentage column widths, or table-layout: fixed etc.

https://jsfiddle.net/tturadqq/

How it works:


Step 1: Just let the table auto-layout do its thing.

When there's one or more columns with a lot of text, it will shrink the other columns as much as possible, then wrap the text of the long columns:

enter image description here


Step 2: Wrap cell contents in a div, then set that div to max-height: 1.1em

(the extra 0.1em is for characters which render a bit below the text base, like the tail of 'g' and 'y')

enter image description here


Step 3: Set title on the divs

This is good for accessibility, and is necessary for the little trick we'll use in a moment.

enter image description here


Step 4: Add a CSS ::after on the div

This is the tricky bit. We set a CSS ::after, with content: attr(title), then position that on top of the div and set text-overflow: ellipsis. I've coloured it red here to make it clear.

(Note how the long column now has a tailing ellipsis)

enter image description here


Step 5: Set the colour of the div text to transparent

And we're done!

enter image description here

Cam Price-Austin
  • 1,738
  • 2
  • 18
  • 31
  • 2
    Awesome, man! (@user9645 - that's not right: have it working with a table rendered with Vue.js - be sure to put the titles on the the div's, not on the td's ) – C12Z Feb 27 '18 at 21:51
  • @ChristianOpitz - Yep I must have messed it up somehow... retried it and it is working. – user9645 Feb 28 '18 at 19:19
  • Just great. And you don't even have to have the same text in the cells (titles are enough), and then you don't need max-height: 1.1em etc - all you need for the divs is position: relative;. – KS74 Feb 24 '19 at 14:54
  • I could even get a working example without the title/after trick, using just divs, by applying similar styles to them. Kjetil Hansen did the same, see his answer below. – KS74 Feb 24 '19 at 16:21
  • For what it's worth, I had to also add a `white-space: normal;` to the `td div::after` css. Then it worked for what I needed wit ellipsis. – aero Aug 30 '19 at 20:47
  • Clever solution. I learned something new about CSS `content` and `attr()` properties. However, I agree with KS74. This solution is over-kill and over-clever. It's hard to understand why you need to set the ellipsis in the `::after`-div when it can simply be done to the `td` (or `td>div`) text itself. Remember that anything generated in the `::after` styling of CSS isn't included in the DOM, and depending on the wider context of where/how the table is being used, this may be a significant problem that needs its own work-around. – cartbeforehorse Dec 05 '21 at 14:29
  • 1
    This is such an underrated answer! This solution is really clever and works especially well in a data grid scenario, where you never really need multiple lines per row. Just a minor improvement I would add is `pointer-events: none` to the `:after` pseudo element, so that you are able to select the text in the rows. – muxcmux Mar 10 '22 at 01:32
26

It seems that if you specify table-layout: fixed; on the table element, then your styles for td should take effect. This will also affect how the cells are sized, though.

Sitepoint discusses the table-layout methods a little here: http://reference.sitepoint.com/css/tableformatting

adriaan
  • 1,088
  • 1
  • 12
  • 29
jongala
  • 497
  • 6
  • 7
19

When it's in percentage table width, or you can't set fixed width on table cell. You can apply table-layout: fixed; to make it work.

table {
  table-layout: fixed;
  width: 100%;
}
td {
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
  border: 1px solid red;
}
<table>
  <tr>
    <td>Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah.</td>
    <td>Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah. Lorem ipsum and dim sum yeah yeah yeah.</td>
  </tr>
</table>
Stickers
  • 75,527
  • 23
  • 147
  • 186
10

Wrap cell content in a flex block. As a bonus, cell auto fits visible width.

table {
  width: 100%;
}

div.parent {
  display: flex;
}

div.child {
  flex: 1;
  width: 1px;
  overflow-x: hidden;
  text-overflow: ellipsis;
}
<table>
  <tr>
    <td>
      <div class="parent">
        <div class="child">
          xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        </div>
      <div>
    </td>
  </tr>
</table>
abbr
  • 5,361
  • 6
  • 30
  • 44
7

This worked in my case, in both Firefox and Chrome:

td {
  max-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%;
}
user1338062
  • 11,939
  • 3
  • 73
  • 67
6

I solved this using an absolutely positioned div inside the cell (relative).

td {
    position: relative;
}
td > div {
    position: absolute;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;        
}

That's it. Then you can either add a top: value to the div or vertically center it:

td > div {      
    top: 0;
    bottom: 0;
    margin: auto 0;
    height: 1.5em; // = line height 
}

To get some space on the right side, you can reduce the max-width a little.

Kjetil Hansen
  • 106
  • 1
  • 4
  • it would be nice with a JSFiddle, as many of the other answers to this popular question. – oma Nov 25 '18 at 20:59
  • Yep, this works, but I used a bit different styles for divs: left:0;top:0;right:0;bottom:0;padding:2px; to get the right position, and to have the same padding as in the table's cells. – KS74 Feb 24 '19 at 16:26
  • 3
    This does force all columns to be equal in width, so it is the same solution as setting the table to fixed-width, just involving an extra element (div). – Dave Munger Oct 30 '20 at 16:44
5

It is worked for me

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

td {
   text-overflow: ellipsis;
   white-space: nowrap;
}
youngoldman
  • 169
  • 1
  • 4
5

For Clean Autosized Tables with Ellipsis

If you can ditch the table tags, then modern CSS has a much cleaner (IMO) solution available: using the grid layout.

You simply need one div or similar to represent the table, with cells inside, e.g.:

<div class="table">
  <div class="cell">text</div>
  <div class="cell">text</div>
  <div class="cell">text</div>
  <div class="cell">text</div>
</div>

Now if I want this to be a 2x2 table then it's simply a case of defining two auto sized columns for the grid:

.table {
  display: grid;
  grid-template-columns: auto auto;
}

For the cells you simply need a few more lines of CSS:

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

Job done! If you need to ensure some columns are wider than others then using the fr units or other available options for the columns template works well.

.table {
  display: grid;
  grid-template-columns: auto auto;
}
.cell {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  border: 1px solid black;
}
<div class="table">
  <div class="cell">long long long long long long long long long long long long long long long long long long long long long long long long</div>
  <div class="cell">text</div>
  <div class="cell">text</div>
  <div class="cell">text</div>
</div>
kirogasa
  • 627
  • 5
  • 19
Matt Lacey
  • 8,227
  • 35
  • 58
  • https://jsfiddle.net/r92c4b0p/ – A__ Sep 24 '21 at 18:51
  • 1
    This is the only solution here that works without messing up the auto-width of table columns. – Evil Pigeon Nov 23 '21 at 10:24
  • This solution requires that you know the number of columns in the table ahead of time (i.e. `grid-template-auto` property needs to define an `auto` keyword for each column in the table). If your table is dynamic and you don't know the number of columns in advance, you need to do some CSS gymnastics to make it work. One possible work-around would be to define: `.table-col-2 { grid-template-columns: auto auto; }` `.table-col-5 { grid-template-columns: auto auto auto auto auto; }` etc. and dynamically apply the correct class in the HTML at runtime. But it's a messy solution. – cartbeforehorse Dec 05 '21 at 15:07
  • @cartbeforehorse If I didn't know the number of columns at run time I'd probably use a CSS variable for the value of `grid-template-columns` and then just set that via JS - no need for any extra classes etc. and it could default to the expected count. – Matt Lacey Dec 06 '21 at 16:05
  • @MattLacey no doubt there are clever JavaScript solutions to make the grid system work dynamically. And for some scenarios your solution would be very elegant. All the same, I can't help but feel that in any dynamic scenario where the aim is to present data in a tabular context, CSS grids just over-engineer the problem. Why use a solution that was designed to address a completely different problem, then have to gloss over the cracks with unnecessary JavaScript, when plain HTML already offers a simple means of presenting 2D/tabular data. – cartbeforehorse Dec 06 '21 at 21:10
  • 1
    Because the standard elements don't work as desired in this specific scenario? I'd always use a table for a table where it works, but in my scenario (and what led me to this question) was I needed a 2x2 grid with 1 to 4 cells that would truncate text in this manner – Matt Lacey Dec 07 '21 at 09:24
  • 1
    Anyone doing this (using the grid method as opposed to the classic ``) should be implementing [aria-roles](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/table_role) for SEO & accessibility concerns.
    – Kalnode Jan 23 '23 at 14:54
-1

XML

<td><div>Your overflowing content here.</div></td>

CSS

td div
{
 max-height: 30vh;
 overflow: auto;
}

Trying to mess with the overall table for this very specific purpose makes no sense. Yes, sometimes it is okay to add an extra element if you explicitly work to not be another 600-divs-nested Twitter/Facebook "developer".

John
  • 1
  • 13
  • 98
  • 177
-7

This is the version that works in IE 9.

http://jsfiddle.net/s27gf2n8/

<div style="display:table; table-layout: fixed; width:100%; " >
        <div style="display:table-row;">
            <div style="display:table-cell;">
                <table style="width: 100%; table-layout: fixed;">
                    <div style="text-overflow:ellipsis;overflow:hidden;white-space:nowrap;">First row. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</div>
                </table>
            </div>
            <div style="display:table-cell;">
                Top right Cell.
            </div>
        </div>
        <div style="display:table-row;">
            <div style="display:table-cell;">
                <table style="width: 100%; table-layout: fixed;">
                    <div style="text-overflow:ellipsis;overflow:hidden;white-space:nowrap;">Second row - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</div>
                </table>
            </div>
            <div style="display:table-cell;">
                Bottom right cell.
            </div>
        </div>
    </div>