I made an image for this question to make it easier to understand.
Is it possible to create an ellipsis on a
Here is a pure CSS way to accomplish this: http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/
Here is a summary:
<html>
<head>
<style>
html, body, p { margin: 0; padding: 0; font-family: sans-serif;}
.ellipsis {
overflow: hidden;
height: 200px;
line-height: 25px;
margin: 20px;
border: 5px solid #AAA; }
.ellipsis:before {
content:"";
float: left;
width: 5px; height: 200px; }
.ellipsis > *:first-child {
float: right;
width: 100%;
margin-left: -5px; }
.ellipsis:after {
content: "\02026";
box-sizing: content-box;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
float: right; position: relative;
top: -25px; left: 100%;
width: 3em; margin-left: -3em;
padding-right: 5px;
text-align: right;
background: -webkit-gradient(linear, left top, right top,
from(rgba(255, 255, 255, 0)), to(white), color-stop(50%, white));
background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white); }
</style>
</head>
<body>
<div class="ellipsis">
<div>
<p>Call me Ishmael.....</p>
</div>
</div>
</body>
</html>
Pure JS solution based on bažmegakapa's solution, and some cleanup to account for people who try to give a height/max-height that is less than the element's lineHeight:
var truncationEl = document.getElementById('truncation-test');
function calculateTruncation(el) {
var text;
while(el.clientHeight < el.scrollHeight) {
text = el.innerHTML.trim();
if(text.split(' ').length <= 1) {
break;
}
el.innerHTML = text.replace(/\W*\s(\S)*$/, '...');
}
}
calculateTruncation(truncationEl);
Maybe quite late but using SCSS you can declare a function like:
@mixin clamp-text($lines, $line-height) {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: $lines;
line-height: $line-height;
max-height: unquote('#{$line-height*$lines}em');
@-moz-document url-prefix() {
position: relative;
height: unquote('#{$line-height*$lines}em');
&::after {
content: '';
text-align: right;
position: absolute;
bottom: 0;
right: 0;
width: 30%;
height: unquote('#{$line-height}em');
background: linear-gradient(
to right,
rgba(255, 255, 255, 0),
rgba(255, 255, 255, 1) 50%
);
}
}
}
And use it like:
.foo {
@include clamp-text(1, 1.4);
}
Which will truncate the text to one line and knowing that it is 1.4 its line-height. The output expected is chrome to render with ...
at the end and FF with some cool fade at the end
Firefox
Chrome
You probably can't do it (currently?) without a fixed-width font like Courier. With a fixed-width font every letter occupies the same horizontal space, so you could probably count the letters and multiply the result with the current font size in ems or exs. Then you would just have to test how many letters fit on one line, and then break it up.
Alternatively, for non-fixed-with fonts you might be able to create a mapping for all possible characters (like i = 2px, m = 5px) and then do the math. A lot of ugly work though.
I have made a version that leaves the html intact. jsfiddle example
jQuery
function shorten_text_to_parent_size(text_elem) {
textContainerHeight = text_elem.parent().height();
while (text_elem.outerHeight(true) > textContainerHeight) {
text_elem.html(function (index, text) {
return text.replace(/(?!(<[^>]*>))\W*\s(\S)*$/, '...');
});
}
}
$('.ellipsis_multiline').each(function () {
shorten_text_to_parent_size($(this))
});
CSS
.ellipsis_multiline_box {
position: relative;
overflow-y: hidden;
text-overflow: ellipsis;
}
jsfiddle example
When I searched solution of multiline ellipsis problem I was surprised that there is no any good one without jQuery. Also there are a few solutions based on 'while' loop, but I think they are not effective and dangerous due to possibility to get into infinite loop. So I wrote this code:
function ellipsizeTextBox(el) {
if (el.scrollHeight <= el.offsetHeight) {
return;
}
let wordArray = el.innerHTML.split(' ');
const wordsLength = wordArray.length;
let activeWord;
let activePhrase;
let isEllipsed = false;
for (let i = 0; i < wordsLength; i++) {
if (el.scrollHeight > el.offsetHeight) {
activeWord = wordArray.pop();
el.innerHTML = activePhrase = wordArray.join(' ');
} else {
break;
}
}
let charsArray = activeWord.split('');
const charsLength = charsArray.length;
for (let i = 0; i < charsLength; i++) {
if (el.scrollHeight > el.offsetHeight) {
charsArray.pop();
el.innerHTML = activePhrase + ' ' + charsArray.join('') + '...';
isEllipsed = true;
} else {
break;
}
}
if (!isEllipsed) {
activePhrase = el.innerHTML;
let phraseArr = activePhrase.split('');
phraseArr = phraseArr.slice(0, phraseArr.length - 3)
el.innerHTML = phraseArr.join('') + '...';
}
}
let el = document.getElementById('ellipsed');
ellipsizeTextBox(el);