7

There are several SO questions regarding making text-overflow: ellipsis work inside a table cell. And the solution is mostly settings table-layout: fixed.

Why can't I do that? Well, because I have dynamic cell widths.

http://jsfiddle.net/d7h437he/2/

The button cell should "fit-to-content" and the copy cell should take the rest. This kind of layout is not possible with table-layout: fixed because the button cell would need to have a width specified, which I can't since it's dynamic.

How to truncate the copy cell?

Note: "not possible" is a valid answer and will be accepted. :)

Aron Woost
  • 19,268
  • 13
  • 43
  • 51
  • This is already answered in another SO post: https://stackoverflow.com/a/44452722/828062 – zendu Jul 11 '17 at 22:39

3 Answers3

8

The problem is that, when you don't use table-layout: fixed, cells are at least as wide as the minimum width required by the content. Therefore, the text can't overflow the cell, it's the table which overflows the container instead.

However, there is a workaround. You can wrap the contents of the cell inside an inner container with

width: 0;
min-width: 100%;

The former will prevent the cell from growing as wide as the text, and the latter will make the inner container fill the whole cell.

.container {
  width: 520px;
  background: yellow;
  padding: 6px;
  margin-bottom: 10px;
}
.table {
  display: table;
  width: 100%;
}
.table > * {
  display: table-cell;
}
.copy {
  width: 100%; 
}
.copy > div {
  width: 0;
  min-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.button {
  white-space: nowrap;
}
<div class="container">
  <div class="table">
    <div class="copy"><div>Lorem ipsum</div></div>
    <div class="button">Save</div>
  </div>
</div>
<div class="container">
  <div class="table">
    <div class="copy"><div>Lorem ipsum</div></div>
    <div class="button">Update and save</div>
  </div>
</div>
<div class="container">
  <div class="table">
    <div class="copy"><div>Lorem ipsum</div></div>
    <div class="button">Cancel</div>
  </div>
</div>
<div class="container">
  <div class="table">
    <div class="copy"><div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Temporibus eius fugit non dolorum ipsam fuga laborum consectetur minus atque nisi nobis voluptatum aut doloremque tenetur maiores officiis quibusdam vitae voluptate.</div></div>
    <div class="button">Cancel</div>
  </div>
</div>
Oriol
  • 274,082
  • 63
  • 437
  • 513
1

This is without using table-cells though. May be something you should consider using.

.container {
  width: 520px;
  background: yellow;
  padding: 6px;
  margin-bottom: 10px;
}
.button {
  white-space: nowrap;
  float: right;
  margin-left: 30px;
}
.copy {
  overflow: hidden; 
}
.copy .wid100{
  width: 100%;
  overflow: hidden;  
  white-space: nowrap; 
  text-overflow: ellipsis;
}
.clear{
  clear: both;
}
<div class="container">
    <div class="table">
      <div class="button">Cancel</div>
      <div class="copy">
          <div class="wid100">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Temporibus eius fugit non dolorum ipsam fuga laborum consectetur minus atque nisi nobis voluptatum aut doloremque tenetur maiores officiis quibusdam vitae voluptate.
          </div>
      </div>
      <div class="clear"></div>
    </div>
</div>
Balaji Viswanath
  • 1,684
  • 1
  • 12
  • 19
0

I ran into this same problem and found a solution using jQuery.

HTML:

<div class="table">
    <div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
    <div class="right">Lorem Ipsum</div>
</div>

In the CSS, you use your standard ellipsis code but add max-width: 0 (as explained here with respect to actual table elements):

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

.left, .right {
    display: table-cell;
    padding: 0 5px 0 5px;

    max-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

If you stopped there, you'd end up with each child div taking up 50% of the total width of the parent div, so you still wouldn't have your fit-to-content dynamic widths. To remedy this, I adapted this code, which calculates the width of the text in an element, to calculate the width and then use that to dynamically set the width of the right column. The left column will then have the ellipsis.

// Calculate width of text from DOM element or string. By Phil Freo <http://philfreo.com>
$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.text(text || this.val() || this.text()).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width();
};

$('.right').on('input', function() {
    var $width = $(this).textWidth(); // Get width of text
    $width += 10; // Add left and right padding
    $(this).width($width); // Set width
}).trigger('input');

Note that the above code requires you to take padding into account; otherwise, the right column will have an ellipsis as well. Here's a fiddle.

To use this in a table with multiple rows, you could modify the jQuery iterate over the cells in a column and set the width of the column to the requisite width of the widest cell in the column. Or, if you know which one is the widest (as it seems you will from your fiddle), you can just direct the jQuery to get the width of that.

Community
  • 1
  • 1
Vincent
  • 2,689
  • 3
  • 24
  • 40