[css] Limit text length to n lines using CSS

Is it possible to limit a text length to "n" lines using CSS (or cut it when overflows vertically).

text-overflow: ellipsis; only works for 1 line text.

original text:

Ultrices natoque mus mattis, aliquam, cras in pellentesque
tincidunt elit purus lectus, vel ut aliquet, elementum nunc
nunc rhoncus placerat urna! Sit est sed! Ut penatibus turpis
mus tincidunt! Dapibus sed aenean, magna sagittis, lorem velit

wanted output (2 lines):

Ultrices natoque mus mattis, aliquam, cras in pellentesque
tincidunt elit purus lectus, vel ut aliquet, elementum...

This question is related to css text overflow ellipsis

The answer is


If you want to focus on each letter you can do like that, I refer to this question

_x000D_
_x000D_
function truncate(source, size) {_x000D_
  return source.length > size ? source.slice(0, size - 1) + "…" : source;_x000D_
}_x000D_
_x000D_
var text = truncate('Truncate text to fit in 3 lines', 14);_x000D_
console.log(text);
_x000D_
_x000D_
_x000D_

If you want to focus on each word you can do like that + space

_x000D_
_x000D_
const truncate = (title, limit = 14) => {  // 14 IS DEFAULT ARGUMENT _x000D_
    const newTitle = [];_x000D_
    if (title.length > limit) {_x000D_
        title.split(' ').reduce((acc, cur) => {_x000D_
            if (acc + cur.length <= limit) {_x000D_
                newTitle.push(cur);_x000D_
            }_x000D_
            return acc + cur.length;_x000D_
        }, 0);_x000D_
_x000D_
        return newTitle.join(' ') + '...'_x000D_
    }_x000D_
    return title;_x000D_
}_x000D_
_x000D_
var text = truncate('Truncate text to fit in 3 lines', 14);_x000D_
console.log(text);
_x000D_
_x000D_
_x000D_

If you want to focus on each word you can do like that + without space

_x000D_
_x000D_
const truncate = (title, limit = 14) => {  // 14 IS DEFAULT ARGUMENT _x000D_
    const newTitle = [];_x000D_
    if (title.length > limit) {_x000D_
        Array.prototype.slice.call(title).reduce((acc, cur) => {_x000D_
            if (acc + cur.length <= limit) {_x000D_
                newTitle.push(cur);_x000D_
            }_x000D_
            return acc + cur.length;_x000D_
        }, 0);_x000D_
_x000D_
        return newTitle.join('') + '...'_x000D_
    }_x000D_
    return title;_x000D_
}_x000D_
_x000D_
var text = truncate('Truncate text to fit in 3 lines', 14);_x000D_
console.log(text);
_x000D_
_x000D_
_x000D_


What you can do is the following:

_x000D_
_x000D_
.max-lines {_x000D_
  display: block;/* or inline-block */_x000D_
  text-overflow: ellipsis;_x000D_
  word-wrap: break-word;_x000D_
  overflow: hidden;_x000D_
  max-height: 3.6em;_x000D_
  line-height: 1.8em;_x000D_
}
_x000D_
<p class="max-lines">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vitae leo dapibus, accumsan lorem eleifend, pharetra quam. Quisque vestibulum commodo justo, eleifend mollis enim blandit eu. Aenean hendrerit nisl et elit maximus finibus. Suspendisse scelerisque consectetur nisl mollis scelerisque.</p>
_x000D_
_x000D_
_x000D_

where max-height: = line-height: × <number-of-lines> in em.


The solution from this thread is to use the jquery plugin dotdotdot. Not a CSS solution, but it gives you a lot of options for "read more" links, dynamic resizing etc.


I've been looking around for this, but then I realize, damn my website uses php!!! Why not use the trim function on the text input and play with the max length....

Here is a possible solution too for those using php: http://ideone.com/PsTaI

<?php
$s = "In the beginning there was a tree.";
$max_length = 10;

if (strlen($s) > $max_length)
{
   $offset = ($max_length - 3) - strlen($s);
   $s = substr($s, 0, strrpos($s, ' ', $offset)) . '...';
}

echo $s;
?>

following CSS class helped me in getting two line ellipsis.

  .two-line-ellipsis {
        padding-left:2vw;
        text-overflow: ellipsis;
        overflow: hidden;
        width: 325px;
        line-height: 25px;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        padding-top: 15px;
    }

I really like line-clamp, but no support for firefox yet.. so i go with a math calc and just hide the overflow

.body-content.body-overflow-hidden h5 {
    max-height: 62px;/* font-size * line-height * lines-to-show(4 in this case) 63px if you go with jquery */
    overflow: hidden;
}
.body-content h5 {
    font-size: 14px; /* need to know this*/
    line-height:1,1; /*and this*/
}

now lets say you want to remove and add this class via jQuery with a link, you will need to have an extra pixel so the max-height it will be 63 px, this is because you need to check every time if the height greather than 62px, but in the case of 4 lines you will get a false true, so an extra pixel will fix this and it will no create any extra problems

i will paste a coffeescript for this just to be an example, uses a couple of links that are hidden by default, with classes read-more and read-less, it will remove the ones that the overflow is not need it and remove the body-overflow classes

jQuery ->

    $('.read-more').each ->
        if $(this).parent().find("h5").height() < 63
             $(this).parent().removeClass("body-overflow-hidden").find(".read-less").remove()
             $(this).remove()
        else
            $(this).show()

    $('.read-more').click (event) ->
        event.preventDefault()
        $(this).parent().removeClass("body-overflow-hidden")
        $(this).hide()
        $(this).parent().find('.read-less').show()

    $('.read-less').click (event) ->
        event.preventDefault()
        $(this).parent().addClass("body-overflow-hidden")
        $(this).hide()
        $(this).parent().find('.read-more').show()

.class{
   word-break: break-word;
   overflow: hidden;
   text-overflow: ellipsis;
   display: -webkit-box;
   line-height: 16px; /* fallback */
   max-height: 32px; /* fallback */
   -webkit-line-clamp: 2; /* number of lines to show */
   -webkit-box-orient: vertical;
}

Working Cross-browser Solution

This problem has been plaguing us all for years.

To help in all cases, I have laid out the CSS only approach, and a jQuery approach in case the css caveats are a problem.

Here's a CSS only solution I came up with that works in all circumstances, with a few minor caveats.

The basics are simple, it hides the overflow of the span, and sets the max height based on the line height as suggested by Eugene Xa.

Then there is a pseudo class after the containing div that places the ellipsis nicely.

Caveats

This solution will always place the ellipsis, regardless if there is need for it.

If the last line ends with an ending sentence, you will end up with four dots....

You will need to be happy with justified text alignment.

The ellipsis will be to the right of the text, which can look sloppy.

Code + Snippet

jsfiddle

_x000D_
_x000D_
.text {_x000D_
  position: relative;_x000D_
  font-size: 14px;_x000D_
  color: black;_x000D_
  width: 250px; /* Could be anything you like. */_x000D_
}_x000D_
_x000D_
.text-concat {_x000D_
  position: relative;_x000D_
  display: inline-block;_x000D_
  word-wrap: break-word;_x000D_
  overflow: hidden;_x000D_
  max-height: 3.6em; /* (Number of lines you want visible) * (line-height) */_x000D_
  line-height: 1.2em;_x000D_
  text-align:justify;_x000D_
}_x000D_
_x000D_
.text.ellipsis::after {_x000D_
  content: "...";_x000D_
  position: absolute;_x000D_
  right: -12px; _x000D_
  bottom: 4px;_x000D_
}_x000D_
_x000D_
/* Right and bottom for the psudo class are px based on various factors, font-size etc... Tweak for your own needs. */
_x000D_
<div class="text ellipsis">_x000D_
  <span class="text-concat">_x000D_
Lorem ipsum dolor sit amet, nibh eleifend cu his, porro fugit mandamus no mea. Sit tale facete voluptatum ea, ad sumo altera scripta per, eius ullum feugait id duo. At nominavi pericula persecuti ius, sea at sonet tincidunt, cu posse facilisis eos. Aliquid philosophia contentiones id eos, per cu atqui option disputationi, no vis nobis vidisse. Eu has mentitum conclusionemque, primis deterruisset est in._x000D_
_x000D_
Virtute feugait ei vim. Commune honestatis accommodare pri ex. Ut est civibus accusam, pro principes conceptam ei, et duo case veniam. Partiendo concludaturque at duo. Ei eirmod verear consequuntur pri. Esse malis facilisis ex vix, cu hinc suavitate scriptorem pri._x000D_
  </span>_x000D_
</div>
_x000D_
_x000D_
_x000D_

jQuery Approach

In my opinion this is the best solution, but not everyone can use JS. Basically, the jQuery will check any .text element, and if there are more chars than the preset max var, it will cut the rest off and add an ellipsis.

There are no caveats to this approach, however this code example is meant only to demonstrate the basic idea - I wouldn't use this in production without improving on it for a two reasons:

1) It will rewrite the inner html of .text elems. whether needed or not. 2) It does no test to check that the inner html has no nested elems - so you are relying a lot on the author to use the .text correctly.

Edited

Thanks for the catch @markzzz

Code & Snippet

jsfiddle

_x000D_
_x000D_
setTimeout(function()_x000D_
{_x000D_
 var max = 200;_x000D_
  var tot, str;_x000D_
  $('.text').each(function() {_x000D_
   str = String($(this).html());_x000D_
   tot = str.length;_x000D_
    str = (tot <= max)_x000D_
     ? str_x000D_
      : str.substring(0,(max + 1))+"...";_x000D_
    $(this).html(str);_x000D_
  });_x000D_
},500); // Delayed for example only.
_x000D_
.text {_x000D_
  position: relative;_x000D_
  font-size: 14px;_x000D_
  color: black;_x000D_
  font-family: sans-serif;_x000D_
  width: 250px; /* Could be anything you like. */_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<p class="text">_x000D_
Old men tend to forget what thought was like in their youth; they forget the quickness of the mental jump, the daring of the youthful intuition, the agility of the fresh insight. They become accustomed to the more plodding varieties of reason, and because this is more than made up by the accumulation of experience, old men think themselves wiser than the young._x000D_
</p>_x000D_
_x000D_
<p class="text">_x000D_
Old men tend to forget what thought was like in their youth;_x000D_
</p>_x000D_
 <!-- Working Cross-browser Solution_x000D_
_x000D_
This is a jQuery approach to limiting a body of text to n words, and end with an ellipsis -->
_x000D_
_x000D_
_x000D_


There's a way to do it using unofficial line-clamp syntax, and starting with Firefox 68 it works in all major browsers.

_x000D_
_x000D_
body {_x000D_
   margin: 20px;_x000D_
}_x000D_
_x000D_
.text {_x000D_
   overflow: hidden;_x000D_
   text-overflow: ellipsis;_x000D_
   display: -webkit-box;_x000D_
   -webkit-line-clamp: 2; /* number of lines to show */_x000D_
   -webkit-box-orient: vertical;_x000D_
}
_x000D_
<div class="text">_x000D_
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam consectetur venenatis blandit. Praesent vehicula, libero non pretium vulputate, lacus arcu facilisis lectus, sed feugiat tellus nulla eu dolor. Nulla porta bibendum lectus quis euismod. Aliquam volutpat ultricies porttitor. Cras risus nisi, accumsan vel cursus ut, sollicitudin vitae dolor. Fusce scelerisque eleifend lectus in bibendum. Suspendisse lacinia egestas felis a volutpat._x000D_
</div>
_x000D_
_x000D_
_x000D_

Unless you care about IE users, there is no need to do line-height and max-height fallbacks.


I have a solution which works well but instead an ellipsis it uses a gradient. It works when you have dynamic text so you don't know if it will be long enough to need an ellipse. The advantages are that you don't have to do any JavaScript calculations and it works for variable width containers including table cells and is cross-browser. It uses a couple of extra divs, but it's very easy to implement.

Markup:

<td>
    <div class="fade-container" title="content goes here">
         content goes here
         <div class="fade">
    </div>
</td>

CSS:

.fade-container { /*two lines*/
    overflow: hidden;
    position: relative;
    line-height: 18px; 
    /* height must be a multiple of line-height for how many rows you want to show (height = line-height x rows) */
    height: 36px;
    -ms-hyphens: auto;
    -webkit-hyphens: auto;
    hyphens: auto;
    word-wrap: break-word;
}

.fade {
        position: absolute;
        top: 50%;/* only cover the last line. If this wrapped to 3 lines it would be 33% or the height of one line */
        right: 0;
        bottom: 0;
        width: 26px;
        background: linear-gradient(to right,  rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%);
}

blog post: http://salzerdesign.com/blog/?p=453

example page: http://salzerdesign.com/test/fade.html


Currently you can't, but in future you will be able to use text-overflow:ellipis-lastline. Currently it's available with vendor prefix in Opera 10.60+: example


Basic Example Code, learning to code is easy. Check Style CSS comments.

_x000D_
_x000D_
table tr {_x000D_
  display: flex;_x000D_
}_x000D_
table tr td {_x000D_
  /* start */_x000D_
  display: inline-block; /* <- Prevent <tr> in a display css */_x000D_
  text-overflow: ellipsis;_x000D_
  white-space: nowrap;_x000D_
  /* end */_x000D_
  padding: 10px;_x000D_
  width: 150px; /* Space size limit */_x000D_
  border: 1px solid black;_x000D_
  overflow: hidden;_x000D_
}
_x000D_
<table>_x000D_
  <tbody>_x000D_
    <tr>_x000D_
      <td>_x000D_
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla egestas erat ut luctus posuere. Praesent et commodo eros. Vestibulum eu nisl vel dui ultrices ultricies vel in tellus._x000D_
      </td>_x000D_
      <td>_x000D_
        Praesent vitae tempus nulla. Donec vel porta velit. Fusce mattis enim ex. Mauris eu malesuada ante. Aenean id aliquet leo, nec ultricies tortor. Curabitur non mollis elit. Morbi euismod ante sit amet iaculis pharetra. Mauris id ultricies urna. Cras ut_x000D_
        nisi dolor. Curabitur tellus erat, condimentum ac enim non, varius tempor nisi. Donec dapibus justo odio, sed consequat eros feugiat feugiat._x000D_
      </td>_x000D_
      <td>_x000D_
        Pellentesque mattis consequat ipsum sed sagittis. Pellentesque consectetur vestibulum odio, aliquet auctor ex elementum sed. Suspendisse porta massa nisl, quis molestie libero auctor varius. Ut erat nibh, fringilla sed ligula ut, iaculis interdum sapien._x000D_
        Ut dictum massa mi, sit amet interdum mi bibendum nec._x000D_
      </td>_x000D_
    </tr>_x000D_
    <tr>_x000D_
      <td>_x000D_
        Sed viverra massa laoreet urna dictum, et fringilla dui molestie. Duis porta, ligula ut venenatis pretium, sapien tellus blandit felis, non lobortis orci erat sed justo. Vivamus hendrerit, quam at iaculis vehicula, nibh nisi fermentum augue, at sagittis_x000D_
        nibh dui et erat._x000D_
      </td>_x000D_
      <td>_x000D_
        Nullam mollis nulla justo, nec tincidunt urna suscipit non. Donec malesuada dolor non dolor interdum, id ultrices neque egestas. Integer ac ante sed magna gravida dapibus sit amet eu diam. Etiam dignissim est sit amet libero dapibus, in consequat est_x000D_
        aliquet._x000D_
      </td>_x000D_
      <td>_x000D_
        Vestibulum mollis, dui eu eleifend tincidunt, erat eros tempor nibh, non finibus quam ante nec felis. Fusce egestas, orci in volutpat imperdiet, risus velit convallis sapien, sodales lobortis risus lectus id leo. Nunc vel diam vel nunc congue finibus._x000D_
        Vestibulum turpis tortor, pharetra sed ipsum eu, tincidunt imperdiet lorem. Donec rutrum purus at tincidunt sagittis. Quisque nec hendrerit justo._x000D_
      </td>_x000D_
    </tr>_x000D_
  </tbody>_x000D_
</table>
_x000D_
_x000D_
_x000D_


As far as I can see, this would be possible only using height: (some em value); overflow: hidden and even then it wouldn't have the fancy ... at the end.

If that is not an option, I think it's impossible without some server side pre-processing (difficult because text flow is impossible to predict reliably) or jQuery (possible but probably complicated).


Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to text

Difference between opening a file in binary vs text How do I center text vertically and horizontally in Flutter? How to `wget` a list of URLs in a text file? Convert txt to csv python script Reading local text file into a JavaScript array Python: How to increase/reduce the fontsize of x and y tick labels? How can I insert a line break into a <Text> component in React Native? How to split large text file in windows? Copy text from nano editor to shell Atom menu is missing. How do I re-enable

Examples related to overflow

Bootstrap button drop-down inside responsive table not visible because of scroll Remove scrollbars from textarea Carry Flag, Auxiliary Flag and Overflow Flag in Assembly Horizontal scroll css? Body set to overflow-y:hidden but page is still scrollable in Chrome How can I add a vertical scrollbar to my div automatically? CSS text-overflow: ellipsis; not working? Have a fixed position div that needs to scroll if content overflows Mobile overflow:scroll and overflow-scrolling: touch // prevent viewport "bounce" Overflow-x:hidden doesn't prevent content from overflowing in mobile browsers

Examples related to ellipsis

What is the hamburger menu icon called and the three vertical dots icon called? Applying an ellipsis to multiline text How to have Ellipsis effect on Text CSS text-overflow: ellipsis; not working? Android, How to limit width of TextView (and add three dots at the end of text)? Why doesn't CSS ellipsis work in table cell? HTML text-overflow ellipsis detection With CSS, use "..." for overflowed block of multi-lines HTML - how can I show tooltip ONLY when ellipsis is activated Limit text length to n lines using CSS