41

I'm trying to achieve a responsive table width text-overflow: ellipsis; in the middle cell that looks like this:

| Button 1 | A one-lined text that is too long and has to be... | Button 2 |

The whole table should have width: 100%; to be as large as the device. I can't set a fixed width on Button 1 nor Button 2 since the application is multilingual (a max-width should be possible though).

I can try whatever I want, the ... only appears when I set a fixed width. How can I tell the middle cell to "use the space available" without the help of JavaScript?

kraftwer1
  • 5,253
  • 10
  • 36
  • 54

7 Answers7

81

This is not really a clean solution, but it uses no JS and works in every browser I've tested.

My solution consists in wrapping the cell's contents inside a table with table-layout: fixed and width: 100%.

See the demo.

Here's the full solution:

<table class="main-table">
    <tr>
        <td class="nowrap">Button 1</td>
        <td>
            <table class="fixed-table">
                <tr>
                    <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus doloremque magni illo reprehenderit consequuntur quia dicta labore veniam distinctio quod iure vitae porro nesciunt. Minus ipsam facilis! Velit sapiente numquam.</td>
                </tr>
            </table>
        </td>
        <td class="nowrap">Button 2</td>
    </tr>
</table>
.main-table {
    width: 100%;
}

.fixed-table {
    /* magic */
    width: 100%;
    table-layout: fixed;
    
    /*not really necessary, removes extra white space */
    border-collapse: collapse;
    border-spacing: 0;
    border: 0;
}
.fixed-table td {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nowrap {
    /* used to keep buttons' text in a single line,
     * remove this class to allow natural line-breaking.
     */
    white-space: nowrap;
}

It's not really clear what's the intent for the side buttons, hence I've used white-space: nowrap to keep them in the same line. Depending on the use case, you may prefer to apply a min-width and let them line-break naturally.

Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
  • Perfecto, it worked like charm.... I was awarding you bounty points but SO says it can't be done before 23 more hrs... – Atul Gupta Oct 27 '13 at 21:09
  • 2
    Heheh no worries, I'd like to see a cleaner answer than this too so let's wait and see. I actually have this answer's code in a production environment, it doesn't feel really clean but yeah, I struggled with it for days and this was the only solution that actually worked in every browser. – Fabrício Matté Oct 27 '13 at 21:10
  • @AtulGupta thanks for trying to add my fiddle to the OP (saw it on the edit review queue), but I guess it's not really the place for it. `;)` Thanks for upvoting my answer, but let's wait to see if anyone comes up with a cleaner solution in the next 24 hours and then you can award the bounty when you feel like. `:P` – Fabrício Matté Oct 27 '13 at 21:20
  • +1 for the solution, because it does not effect current styling of your table. just 1 cell to update. – muneebShabbir May 30 '14 at 05:55
  • awesome (common meaning) – Michael Brennt Nov 26 '14 at 15:03
  • for anyone who, like me, liked the answer but doesn't want all that extra markup here's [css tables](http://stackoverflow.com/a/40518661/2518317) – Hashbrown Nov 10 '16 at 01:35
  • This looks gross, but it does work very solidly, even in IE. I don't want to use css tables, I prefer to use actual tables. This solution is easily encapsulated in an angular component or the like. – Chris Baker Jun 04 '19 at 17:33
19

Set your 100% width on the table and specify a fixed table-layout:

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

Then, set the following for whichever table cell should have the ellipsis:

td:nth-child(2) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

Voila! Responsive table with an ellipsis overflow!

Demo: http://jsfiddle.net/VyxES/

pete
  • 24,141
  • 4
  • 37
  • 51
  • 1
    It is a nice solution, the only drawback of applying `table-layout: fixed` is that it splits the width of cells equally (unless manually set) instead of based on content. – Fabrício Matté Oct 27 '13 at 20:52
  • True, but the OP requested a solution that did not specify a width on individual table cells (and thanks!). – pete Oct 27 '13 at 20:53
  • 3
    Agreed, big drawback, the OP wanted the 1st and 3rd cells to be only as wide as their content and have the center cell take up the remaining width. – Jonathan Julian Jan 29 '14 at 18:33
  • 1
    @JonathanJulian: Please point out where in the OP that requirement is stated. – pete Jan 29 '14 at 19:07
  • Thank you for this - of all the answers I've read on this subject, this is the one that worked for me. – Ryan Burney Feb 17 '15 at 06:03
  • @FabrícioMatté & JonathanJulian I have a [solution](http://stackoverflow.com/a/40518661/2518317) without `fixed` layout below – Hashbrown Nov 10 '16 at 01:31
  • This worked for us. We hate the nested table markup, and the fact that this is even necessary, but it is the most robust and cross-browser solution that doesn't involve static table cell widths or abandoning semantic table markup for the entire app just to get div-based tables in the 2% of the cases where we need to truncate some text. – Chris Baker Jun 03 '19 at 14:53
10

HTML

<tr>
    <td>
        <span class="ellipsis"> A very looooooooooooooooooooooooooooooong string</span>
    </td>
</tr>

CSS

td {
    position: relative;
}

.ellipsis {
    /*Here is the trick:*/
    position: absolute;
    width: 100%;
    /*End of the trick*/

    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
}
babich.ss
  • 177
  • 1
  • 6
  • This is the best solution for me. I saw that, span is get top: 10 by default. It will be beneficial to add a top value in elipsis class. – efirat Sep 21 '16 at 13:45
4

A cleaner way would be to simply set a max-width on the td.

Based on @Fabrício Matté's reply,

http://jsfiddle.net/V83Ae/89/

<table class="main-table">
<tr>
    <td class="nowrap">Button 1</td>
    <td class="truncate">
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus doloremque magni illo reprehenderit consequuntur quia dicta labore veniam distinctio quod iure vitae porro nesciunt. Minus ipsam facilis! Velit sapiente numquam.</td>
    <td class="nowrap">Button 2</td>
</tr>

And

body { margin: 0; }

.main-table {
    width: 100%;
}

.truncate {
    text-overflow: ellipsis;
    white-space  : nowrap;
    overflow     : hidden;
    max-width    : 100px; /* Can be any size, just small enough */
}

.nowrap {
    white-space: nowrap;
}

I have no idea why this works, but it does, so if someone can figure how why applying a max-width works then please let me know as I did it by accident.

Gerald
  • 49
  • 1
3

After banging my head for hours, with no solution that worked, finally found it.

The element you want for the base of the overflow nees a min/max width, where the max is inferior to the min width. You can then overflow the lement or a child of it, where you can set the with whatever way you choose: %, px, auto.

I tried it in more than one tricky situation and it works on all.

I'll try to post a fiidle with my examples but this should help you going.

/* Apply on base element for proper overflow */
max-width: 1px;
min-width: 10000px;

/* Apply on self or child, according to need */
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
JDB
  • 25,172
  • 5
  • 72
  • 123
alfatreze
  • 31
  • 1
1

Here you go

<div class="container">
  <div>
    Button 1
  </div>
  <div class="fill">
    <div class="lockText">
      A one-lined text that is too long and has to be...
    </div>
  </div>
  <div>
    Button 2
  </div>
</div>

The trick is to set up a table layout with a cell that takes up leftover space first (css tables, mind you!).

.container {
  display: table;
  width: 100%;
}

.container > div {
  display: table-cell;
  white-space: nowrap;
  position : relative;
  width : auto;

  /*make it easier to see what's going on*/
  padding : 2px;
  border : 1px solid gray;
}

.container > .fill {
  width : 100%;
}

Then add your text that constrains itself within.

.lockText {
  position : absolute;
  left : 0;
  right : 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
Hashbrown
  • 12,091
  • 8
  • 72
  • 95
-1

[update] My apologies, does not seem to work 'just like that': http://jsfiddle.net/kQKfc/1/

Will leave it here though, because it certain situations it does the trick for us.
[/update]

We have this css in our project, give it a shot:

.nowr
{
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
TweeZz
  • 4,779
  • 5
  • 39
  • 53