6

I am fairly sure this is impossible with just html/css, but I wanted to ask just in case. Let's say I have <div> inside a <td>, the div has the overflow: hidden; style. Instead of the overflow just being cut off, I want to:

  1. Detect that there is overflow.
  2. React by deleting the last 3 letters of div content and add a "..." at the end.

Edit: I missed a critical detail when originally asking the question - is this possible to do with overflow-y, so I can still have multiple lines of text before it generates the "..."?

PLNKR for testing

VSO
  • 11,546
  • 25
  • 99
  • 187
  • 5
    Search for `css ellipsis` - or go here - https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ - it does exactly what you want to do – StudioTime Nov 19 '15 at 13:46
  • 1
    Yes, it is - see [this codepen](http://codepen.io/barneycarroll/pen/acJpA) for an example with multiple lines of text that eventually overflows. – Sean Vieira Nov 19 '15 at 14:20
  • 1
    Looks like that pretty much does it Sean, though I haven't applied to my use yet, thank you. The problem is that I can't use before/after here because I can only use in-line styles, but that's my weird overly-specific application. – VSO Nov 19 '15 at 14:30

4 Answers4

7

Example taken from the link I provided in the OP comments:

.element-to-cut-off {
  width: 250px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

From your plnkr, change div class to this:

div{
    background-color:cyan;
    width: 80px;
    height: 40px; 
    overflow: hidden; 
    white-space: nowrap;
    text-overflow: ellipsis;
}

Change your plnkr to this for multi line:

div{
  background-color:cyan;
  width: 80px;
  height: 40px; 
  overflow: hidden; 
  -webkit-line-clamp: 2; // number of lines before ellipsis kicks in
  -webkit-box-orient: vertical;
  display: -webkit-box;
  overflow: hidden;
  text-overflow: ellipsis;
}

I will stress I don't know which browsers can use this css3 and don't have time to test all, but works fine in Chrome 46

StudioTime
  • 22,603
  • 38
  • 120
  • 207
  • 1
    Sorry I didn't see your answer when I posted mine, I removed it now. – Jonas Grumann Nov 19 '15 at 13:48
  • Hey, thanks Darren, I will test and come back to accept the answer or ask questions. – VSO Nov 19 '15 at 13:49
  • 1
    Without the `white-space` and `text-overflow` the div actually accepts two lines of text before overflowing. Is there any way it still accepts two lines? Or this is enough for the OP?. I would recommend setting the title of the div to te full text, or using a tooltip, so the user can still read the full text if he wants. – Alvaro Flaño Larrondo Nov 19 '15 at 13:56
  • Darren, I have an annoying addition to this question - is there a way to make it work with overflow-y? Edit: Looks like Alvaro beat me to it - that's exactly what I need. – VSO Nov 19 '15 at 13:57
  • @VSO Have a look at the amended answer – StudioTime Nov 19 '15 at 14:04
  • Take a look at [this codepen](http://codepen.io/barneycarroll/pen/acJpA) from the comments on the linked example - it solves the overflow problem with no extra elements *and* without relying on `-webkit-line-clamp` so you can have multiple lines before overflow. – Sean Vieira Nov 19 '15 at 14:20
2

Taking a leaf from barneycarroll's codepen here is a solution that solves the overflow problem with only one extra element (a wrapper) and without relying on -webkit-line-clamp to allow multiple lines before overflow:

/*
The ellipsis classes reveal a '...'
if there is more content that isn't being displayed

The ellipsis-container class adds padding to the container
to stop the ellipsis clipping text
*/

.ellipsis-container {
  padding-right: 1em;
  position: relative;
}

.ellipsis {
  background: inherit;
  display: inline;
}

.ellipsis:before,
.ellipsis:after {
  background: inherit;
  position: absolute;
}

/* Provide the actual ellipsis character at the bottom right */
.ellipsis:before {
  content: '\2026';
  bottom: 0;
  right: 0;
}

/*
Hide the ellipsis from the `:before` pseudo-element
until the text reaches the last line (at which point
this element will be in the hidden overflow).
*/
.ellipsis:after {
  content: '';
  height: 100%;
  width: 100%;
}

/* Clamping is just a mechanism to limit the number of lines that can be displayed in a container */
.clamped {
  line-height: 1.5;
  overflow: hidden;
}

.clamped-2 {
  /* Clamp to 2 lines, ie line-height x 2: */
  max-height: 3em;
}

.clamped-3 {
  max-height: 4.5em;
}

/* Generic styles */
body {
  background: #cfdbec;
  color: #cfdbec;
  font: 12px/1.5 Consolas, monospace;
  margin: 0;
}

p {
  /* Demonstrate that this technique works on non-solid backgrounds. This background image causes zebra striping. It happens to be 36px high, ie twice the line height ( 12px * 1.5 * 2 ). Background-sizing may be necessary. */
  background-image: url(data:image/gif;base64,R0lGODlhAQAkAIAAAERERC8vLyH5BAAAAAAALAAAAAABACQAAAIHhI95we3fCgA7);
  /* This part is essential to keep the ellipsis bits in sync */
  background-attachment: fixed;
  border: 1.5em solid #2f2f2f;
  /* Keeping a tight vertical rythm (everything in multiples of 1.5em) makes sure the background image will always align */
  margin: 1.5em 0;
}
<p class="ellipsis-container clamped clamped-2">
    <span class="ellipsis">
        There's a bit of text here. Enough to trigger the effect? Probably not.
    </span>
</p>
<p class="ellipsis-container clamped clamped-3">
    <span class="ellipsis">
        But more text here (the same markup structure though): if the text overflows from the clamped paragraph's height, the ellipse will show. You may have to resize the browser window (or this paragraph's container) to see the effect in action.  Once the text is long enough the ellipsis show up and everything gets cut off.  The `1em` of padding on `ellipsis-container` ensures that no word is every *under* the ellipsis.
    </span>
</p>
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
2

I just wanted to add a Javascript approach. I have never used Angular so I did it using jQuery and a function found here. Take notice that the title attribute is updated so the full text can be read if you place the mouse over it.

$('input').on('keyup',function(){
    var $input = $(this);
    var $div = $('table div');
    var text = $(this).val();

    $div.attr('title',text);
    $div.text(text);

    while(checkOverflow($div[0])){
        var short_text = $div.text().substring(0, $div.text().length - 4) + "...";
        $div.text(short_text);
    }
});

Here is a working JSFiddle.

Community
  • 1
  • 1
Alvaro Flaño Larrondo
  • 5,516
  • 2
  • 27
  • 46
  • 2
    Unfortunately I can't use javascript at all, I do appreciate the answer, I am sure people will find it helpful later on. As a random note, I find people falling back to jQuery from angular when dom manipulation is needed. – VSO Nov 19 '15 at 15:42
0

You need very little CSS in order to create your desired effect, namely:

HTML

<div class="ellipsis">a very long text goes here</div>

CSS

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

Hope it helps!

Community
  • 1
  • 1
kunambi
  • 756
  • 1
  • 10
  • 25