66

I have a <p> tag with a specific width and height.

I want to use text-overflow:ellipsis to get ... if the text in the tag is too long.

Is this possible to solve with css on multiline text?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Johan
  • 18,814
  • 30
  • 70
  • 88
  • its worth pointing out that `text-overflow:ellipsis` doesn't work at all in Firefox yet (apparently planned for FF7 when it gets released). – Spudley Jul 30 '11 at 15:00
  • Does this answer your question? [css ellipsis on second line](https://stackoverflow.com/questions/5269713/css-ellipsis-on-second-line) – Penny Liu Apr 29 '20 at 06:01

12 Answers12

39

Googling doesn't reveal anything even remotely promising, so I'm going to say that it's not possible.

I did find text-overflow: -o-ellipsis-lastline, but it only works in Opera: http://people.opera.com/dstorey/text/text-overflow.html (mirror: http://jsbin.com/exugux/)

There's also a similar WebKit-only solution: http://dropshado.ws/post/1015351370/webkit-line-clamp

thirtydot
  • 224,678
  • 48
  • 389
  • 349
  • 4
    I believe this right. Everything I've ever read indicates nowrap is required – Richard H Jul 04 '11 at 14:01
  • 1
    I just added an answer that links to a post where someone implements a passable css-only solution to this. It's not quite perfect, but I found it reasonable. – Kaleb Pederson Feb 27 '13 at 16:45
16

You can do it with css. It only works in webkit browsers but has a fallback for the other ones.

use :

display: -webkit-box;
-webkit-line-clamp: $lines-to-show;
-webkit-box-orient: vertical;
height: $font-size*$line-height*$lines-to-show; /* Fallback for non-webkit */

along with:

max-width: $maxwidth;
overflow: hidden;
text-overflow: ellipsis;

Here is the fiddle: demo

Harish Ambady
  • 12,525
  • 4
  • 29
  • 54
13

I'm posting this because I believe my solution is less complex than the popular one, which involves pseudo elements and float behaviour. I recently had to create a solution which would work in IE7, so pseudo elements weren't an option in the first place.

The technique involves 4 elements:

  • A block level container which determines the maximum height of the contents
  • An inline wrapper for the text content
  • An ellipsis contained within the inline wrapper
  • A 'fill' element, also inside the inline wrapper, that occludes the ellipsis when the text content doesn't exceed the dimensions of the container

As with previous CSS-only solutions, the technique demands a solid colour background or fixed position background image for the contents: the ellipsis needs to obscure parts of the text, and the fill needs to obscure the ellipsis. You can do a fancy gradient effect to make the text fade into the ellipsis, but I'll leave that cosmetic detail to discretion.

HTML structure

<!-- The block level container. `clamped-2` for 2 lines height -->
<p class="clamped clamped-2">
  <!-- The inline wrapper -->
  <span class="text">
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy
    nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 
    Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
    lobortis nisl ut aliquip ex ea commodo consequat.
    <!-- The ellipsis, which can contain anything you want - 
         (a 'more' link, for example) -->
    <span class="ellipsis">
      &#133;
    </span>
    <!-- The fill, which covers the ellipsis when the text doesn't overflow -->
    <span class="fill"></span>
  </span>
</p>

CSS

body {
  /* We need a solid background or background-position: fixed */
  background: #fff;
  /* You'll need to know the line height to clamp on line breaks */
  line-height: 1.5;
}

.clamped {
  overflow: hidden;
  position: relative;
}

/* Clamp to 2 lines, ie line-height x 2:
   Obviously any number of these classes can be written as needed
 */
.clamped-2 {
  max-height: 3em;
}

/* The ellipsis is always at the bottom right of the container,
   but when the text doesn't reach the bottom right...
 */
.clamped .ellipsis {
  background: #fff;
  bottom: 0;
  position: absolute;
  right: 0;
}

/* ...It's obscured by the fill, which is positioned at the bottom right 
   of the text, and occupies any remaining space.
 */
.clamped .fill {
  background: #fff; 
  height: 100%;
  position: absolute;
  width: 100%;
}

Here's a fiddle demonstrating it: resize your browser's width or change the text to see it shift from ellipsis to no-ellipsis.

Aside from the arbitrary elegance factor, I believe this is more performant than the popular solution because it doesn't rely on floats (which require a lot of repainting) — absolute positioning is much simpler to compute since there are no inter-dependencies when calculating layout.

Barney
  • 16,181
  • 5
  • 62
  • 76
  • > I believe this is more performant Do you have numbers? How much more? – David Miller Jun 19 '13 at 15:59
  • Alas, belief presupposes the absence of certainty! You could do [paint time comparisons with Chrome Dev Tools](http://updates.html5rocks.com/2013/02/Profiling-Long-Paint-Times-with-DevTools-Continuous-Painting-Mode), but I suspect there are easier ways of generating numbers. – Barney Jun 19 '13 at 16:27
  • Adding display: block to .clamped .fill fixes an issue where if there is only one line of content it pushed the fill so far right that the .ellipsis is uncovered even though there's no overflow. Add display block forces .fill under the content. – Scott Rickman May 01 '15 at 09:45
  • mmm i think is not a very clean solution, you are limited to the background color, if you have different bg colors, is not good :( – msqar Oct 22 '15 at 18:10
  • 1
    @msqar you can use fixed (unsized) background-images too (see [demo](http://codepen.io/barneycarroll/pen/acJpA)), but yes - that is a limitation. Anything else would require Javascript. Depends on your definition of 'clean' :) – Barney Oct 23 '15 at 10:01
  • there's an edge case here right at the point of overflow, where only part of the ellipsis shows up. Is there a way to fix? – Jason S Dec 29 '15 at 22:08
5

I wrote a javascript function to fix the multiline ellipsis problem

function ellipsizeTextBox(id) {

    var el = document.getElementById(id);
    var keep = el.innerHTML;
    while(el.scrollHeight > el.offsetHeight) {
        el.innerHTML = keep;
        el.innerHTML = el.innerHTML.substring(0, el.innerHTML.length-1);
        keep = el.innerHTML;
        el.innerHTML = el.innerHTML + "...";
    }   
}

hope this helps!

user1152475
  • 51
  • 1
  • 3
4

I found a solution for multi-line cross-browser pure CSS ellipsis. I tried lots of solutions and only this one worked out only using CSS. I had a div with a dynamic width and had to set the height.

Here's the link: http://hackingui.com/front-end/a-pure-css-solution-for-multiline-text-truncation/

3

Modified the function by user1152475 so it works word by word (space delimited) rather than character by character.

function ellipsizeTextBox(id) {
    var el = document.getElementById(id);
    var wordArray = el.innerHTML.split(' ');
    while(el.scrollHeight > el.offsetHeight) {
        wordArray.pop();
        el.innerHTML = wordArray.join(' ')  + '...';
    }   
}

Note, for both solutions, the box must have a set height.

Community
  • 1
  • 1
LocalPCGuy
  • 6,006
  • 2
  • 32
  • 28
1

HTML offers no such feature, and this is very frustrating.

That's why i have developped a small library to deal with this issue. The library provides objects to modelize and perform letter-level text rendering. This should do just what you need:

Read more at http://www.samuelrossille.com/home/jstext for screenshot, tutorial, and dowload link.

Samuel Rossille
  • 18,940
  • 18
  • 62
  • 90
  • Looks helpful. A live demo on your site would be useful. Also, testing `jstext-examples.html` in IE9 and resizing produced this, which is obviously a little broken: http://i.stack.imgur.com/aoA1i.png – thirtydot May 22 '12 at 21:05
  • @thirtydot Thanks for the feedback. Bug fixed and live demo added! – Samuel Rossille May 23 '12 at 12:24
0

As pointed out before there is a weird way to accomplish this with a webkit-box posted by David DeSandro:

  elements_to_style {
      display: -webkit-box;
      overflow : hidden;
      text-overflow: ellipsis
      -webkit-line-clamp: number_of_lines_you_want;
      -webkit-box-orient: vertical;
  }

link http://dropshado.ws/post/1015351370/webkit-line-clamp

Tamo Maes
  • 355
  • 3
  • 6
0

Hey you can do it this way using css.

For Chrome & Safari

.block-with-text {
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;  
}

For Firefox & Internet explorer

* styles for '...' */ 
.block-with-text {
  /* hide text if it more than N lines  */
  overflow: hidden;
  /* for set '...' in absolute position */
  position: relative; 
  /* use this value to count block height */
  line-height: 1.2em;
  /* max-height = line-height (1.2) * lines max number (3) */
  max-height: 3.6em; 
  /* fix problem when last visible word doesn't adjoin right side  */
  text-align: justify;  
  /* place for '...' */
  margin-right: -1em;
  padding-right: 1em;
}
/* create the ... */
.block-with-text:before {
  /* points in the end */
  content: '...';
  /* absolute position */
  position: absolute;
  /* set position to right bottom corner of block */
  right: 0;
  bottom: 0;
}
/* hide ... if we have text, which is less than or equal to max lines */
.block-with-text:after {
  /* points in the end */
  content: '';
  /* absolute position */
  position: absolute;
  /* set position to right bottom corner of text */
  right: 0;
  /* set width and height */
  width: 1em;
  height: 1em;
  margin-top: 0.2em;
  /* bg color = bg color under block */
  background: white;
}
Dr. Piyush Dholariya
  • 1,266
  • 16
  • 31
0

just in case someone reach here, may this is a solution for you? pure css cross-browser. http://codepen.io/issactomatotan/pen/LkJbjO

<div style="position:relative;width:100%;max-height:40px;overflow:hidden;font-size:16px;line-height:20px;border:1px solid red;">
<p class="pp">asd asdasd asd asd asdasd a asdasd a sdasd asdasd asdaasd asd asd d asasas das dasdd asddasd asdasd asdsdasd asd<span class="bb"></span></p>

0

I've fiddled with most of these solutions and your best bet is to use the solid clamp.js plugin. It works in all environments and has a tiny footprint minified (3K).

serraosays
  • 7,163
  • 3
  • 35
  • 60
0

.minHeightg {
  height: 5.6rem !important;
  width: 20%;
}

.productOverflow {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  line-height: 16px;
  /* fallback */
  max-height: 3.6rem;
  /* fallback */
  -webkit-line-clamp: 3;
  /* number of lines to show */
  -webkit-box-orient: vertical;
}

/*firefox*/
@-moz-document url-prefix() {
  .productOverflow {
    overflow: hidden;
    text-overflow: ellipsis;
    display: -moz-box !important;
    line-height: 16px;
    /* fallback */
    max-height: 3.6rem;
    /* fallback */
    -moz-line-clamp: 3;
    /* number of lines to show */
    -moz-box-orient: vertical;
  }
}
<div class="minHeightg">
  <p class="productOverflow">Some quick example text to build on the card title .</p>
</div>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
  • Unfortunately, Mozilla Firefox does not support "line-clamp" property. You can't achieve multiline ellipsis on firefox with the above code. – Morez Apr 21 '17 at 03:41
  • Yeah, you should test on Firefox, I swear it still doesn't support. – newbie May 31 '17 at 02:46