with
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
"..." will be shown in the end of the line if overflowed. However, this will be shown only in one line. But I would like it to be shown in multi-lines.
It may looks like:
+--------------------+
|abcde feg hij dkjd|
|dsji jdia js ajid s|
|jdis ajid dheu d ...|/*Here it's overflowed, so "..." is shown. */
+--------------------+
There are many answers here but I needed one that was:
The caveat is that it doesn't provide an ellipsis for the browsers that don't support the -webkit-line-clamp
rule (currently IE, Edge, Firefox) but it does use a gradient to fade their text out.
.clampMe {_x000D_
position: relative;_x000D_
height: 2.4em; _x000D_
overflow: hidden;_x000D_
}_x000D_
_x000D_
.clampMe:after {_x000D_
content: "";_x000D_
text-align: right;_x000D_
position: absolute;_x000D_
bottom: 0;_x000D_
right: 0;_x000D_
width: 50%;_x000D_
height: 1.2em; /* Just use multiples of the line-height */_x000D_
background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 80%);_x000D_
}_x000D_
_x000D_
/* Now add in code for the browsers that support -webkit-line-clamp and overwrite the non-supportive stuff */_x000D_
@supports (-webkit-line-clamp: 2) {_x000D_
.clampMe {_x000D_
overflow: hidden;_x000D_
text-overflow: ellipsis;_x000D_
display: -webkit-box;_x000D_
-webkit-line-clamp: 2;_x000D_
-webkit-box-orient: vertical;_x000D_
}_x000D_
_x000D_
.clampMe:after {_x000D_
display: none;_x000D_
}_x000D_
}
_x000D_
<p class="clampMe">There's a lot more text in here than what you'll ever see. Pellentesque habitant testalotish morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
_x000D_
You can see it in action in this CodePen and you can also see a Javascript version here (no jQuery).
thanks @balpha and @Kevin, I combine two method together.
no js needed in this method.
you can use background-image
and no gradient needed to hide dots.
the innerHTML
of .ellipsis-placeholder
is not necessary, I use .ellipsis-placeholder
to keep the same width and height with .ellipsis-more
.
You could use display: inline-block
instead.
.ellipsis {_x000D_
overflow: hidden;_x000D_
position: relative;_x000D_
}_x000D_
.ellipsis-more-top {/*push down .ellipsis-more*/_x000D_
content: "";_x000D_
float: left;_x000D_
width: 5px;_x000D_
}_x000D_
.ellipsis-text-container {_x000D_
float: right;_x000D_
width: 100%;_x000D_
margin-left: -5px;_x000D_
}_x000D_
.ellipsis-more-container {_x000D_
float: right;_x000D_
position: relative;_x000D_
left: 100%;_x000D_
width: 5px;_x000D_
margin-left: -5px;_x000D_
border-right: solid 5px transparent;_x000D_
white-space: nowrap;_x000D_
}_x000D_
.ellipsis-placeholder {/*keep text around ,keep it transparent ,keep same width and height as .ellipsis-more*/_x000D_
float: right;_x000D_
clear: right;_x000D_
color: transparent;_x000D_
}_x000D_
.ellipsis-placeholder-top {/*push down .ellipsis-placeholder*/_x000D_
float: right;_x000D_
width: 0;_x000D_
}_x000D_
.ellipsis-more {/*ellipsis things here*/_x000D_
float: right;_x000D_
}_x000D_
.ellipsis-height {/*the total height*/_x000D_
height: 3.6em;_x000D_
}_x000D_
.ellipsis-line-height {/*the line-height*/_x000D_
line-height: 1.2;_x000D_
}_x000D_
.ellipsis-margin-top {/*one line height*/_x000D_
margin-top: -1.2em;_x000D_
}_x000D_
.ellipsis-text {_x000D_
word-break: break-all;_x000D_
}
_x000D_
<div class="ellipsis ellipsis-height ellipsis-line-height">_x000D_
<div class="ellipsis-more-top ellipsis-height"></div>_x000D_
<div class="ellipsis-text-container">_x000D_
<div class="ellipsis-placeholder-top ellipsis-height ellipsis-margin-top"></div>_x000D_
<div class="ellipsis-placeholder">_x000D_
<span>...</span><span>more</span>_x000D_
</div>_x000D_
<span class="ellipsis-text">text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </span>_x000D_
</div>_x000D_
<div class="ellipsis-more-container ellipsis-margin-top">_x000D_
<div class="ellipsis-more">_x000D_
<span>...</span><span>more</span>_x000D_
</div>_x000D_
</div>_x000D_
</div>
_x000D_
Great question... I wish there was an answer, but this is the closest you can get with CSS these days. No ellipsis, but still pretty usable.
overflow: hidden;
line-height: 1.2em;
height: 3.6em; // 3 lines * line-height
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
The link below provides a pure HTML / CSS solution to this problem.
Browser support - as stated in the article:
So far we have tested on Safari 5.0, IE 9 (must be in standards mode), Opera 12 and Firefox 15.
Older browsers will still work quite well, as the meat of the layout is in normal positioning, margin and padding properties. if your platform is older (e.g. Firefox 3.6, IE 8), you can use the method but redo the gradient as a standalone PNG image or DirectX filter.
http://www.mobify.com/dev/multiline-ellipsis-in-pure-css
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); }
<div class="ellipsis">
<div>
<p>Call me Ishmael. Some years ago – never mind how long precisely – having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen, and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off – then, I account it high time to get to sea as soon as I can.</p>
</div>
</div>
(resize browser's window for testing)
Bit late to this party but I came up with, what I think, is a unique solution. Rather than trying to insert your own ellipsis through css trickery or js I thought i'd try and roll with the single line only restriction. So I duplicate the text for every "line" and just use a negative text-indent to make sure one line starts where the last one stops. FIDDLE
CSS:
#wrapper{
font-size: 20pt;
line-height: 22pt;
width: 100%;
overflow: hidden;
padding: 0;
margin: 0;
}
.text-block-line{
height: 22pt;
display: inline-block;
max-width: 100%;
overflow: hidden;
white-space: nowrap;
width: auto;
}
.text-block-line:last-child{
text-overflow: ellipsis;
}
/*the follwing is suboptimal but neccesary I think. I'd probably just make a sass mixin that I can feed a max number of lines to and have them avialable. Number of lines will need to be controlled by server or client template which is no worse than doing a character count clip server side now. */
.line2{
text-indent: -100%;
}
.line3{
text-indent: -200%;
}
.line4{
text-indent: -300%;
}
HTML:
<p id="wrapper" class="redraw">
<span class="text-block-line line1">This text is repeated for every line that you want to be displayed in your element. This example has a max of 4 lines before the ellipsis occurs. Try scaling the preview window width to see the effect.</span>
<span class="text-block-line line2">This text is repeated for every line that you want to be displayed in your element. This example has a max of 4 lines before the ellipsis occurs. Try scaling the preview window width to see the effect.</span>
<span class="text-block-line line3">This text is repeated for every line that you want to be displayed in your element. This example has a max of 4 lines before the ellipsis occurs. Try scaling the preview window width to see the effect.</span>
<span class="text-block-line line4">This text is repeated for every line that you want to be displayed in your element. This example has a max of 4 lines before the ellipsis occurs. Try scaling the preview window width to see the effect.</span>
</p>
More details in the fiddle. There is an issue with the browser reflowing that I use a JS redraw for and such so do check it out but this is the basic concept. Any thoughts/suggestions are much appreciated.
Here's a recent css-tricks article which discusses this.
Some of the solutions in the above article (which are not mentioned here) are
1) -webkit-line-clamp
and 2) Place an absolutely positioned element to the bottom right with fade out
Both methods assume the following markup:
<div class="module"> /* Add line-clamp/fade class here*/
<p>Text here</p>
</div>
with css
.module {
width: 250px;
overflow: hidden;
}
line-clamp FIDDLE (..for a maximum of 3 lines)
.line-clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: 3.6em; /* I needed this to get it to work */
}
Let's say you set the line-height to 1.2em. If we want to expose three lines of text, we can just make the height of the container 3.6em (1.2em × 3). The hidden overflow will hide the rest.
p
{
margin:0;padding:0;
}
.module {
width: 250px;
overflow: hidden;
border: 1px solid green;
margin: 10px;
}
.fade {
position: relative;
height: 3.6em; /* exactly three lines */
}
.fade:after {
content: "";
text-align: right;
position: absolute;
bottom: 0;
right: 0;
width: 70%;
height: 1.2em;
background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
}
We can use @supports to apply webkit's line-clamp on webkit browsers and apply fade out in other browsers.
@supports line-clamp with fade fallback fiddle
<div class="module line-clamp">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</div>
.module {
width: 250px;
overflow: hidden;
border: 1px solid green;
margin: 10px;
}
.line-clamp {
position: relative;
height: 3.6em; /* exactly three lines */
}
.line-clamp:after {
content: "";
text-align: right;
position: absolute;
bottom: 0;
right: 0;
width: 70%;
height: 1.2em;
background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
}
@supports (-webkit-line-clamp: 3) {
.line-clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height:3.6em; /* I needed this to get it to work */
height: auto;
}
.line-clamp:after {
display: none;
}
}
Just want to add to this question for completeness sake.
javascript solution will be better
is-ellipsis
class if the window resize or elment changeElement.getClientRects()
works like this
each rects in the same row has the same top
value, so find out the rects with different top
value, like this
function getRowRects(element) {
var rects = [],
clientRects = element.getClientRects(),
len = clientRects.length,
clientRect, top, rectsLen, rect, i;
for(i=0; i<len; i++) {
has = false;
rectsLen = rects.length;
clientRect = clientRects[i];
top = clientRect.top;
while(rectsLen--) {
rect = rects[rectsLen];
if (rect.top == top) {
has = true;
break;
}
}
if(has) {
rect.right = rect.right > clientRect.right ? rect.right : clientRect.right;
rect.width = rect.right - rect.left;
}
else {
rects.push({
top: clientRect.top,
right: clientRect.right,
bottom: clientRect.bottom,
left: clientRect.left,
width: clientRect.width,
height: clientRect.height
});
}
}
return rects;
}
...more
like this
like this
I found a javascript trick, but you have to use the length of the string. Lets say you want 3 lines of width 250px, you can calculate the length per line i.e.
//get the total character length.
//Haha this might vary if you have a text with lots of "i" vs "w"
var totalLength = (width / yourFontSize) * yourNumberOfLines
//then ellipsify
function shorten(text, totalLength) {
var ret = text;
if (ret.length > totalLength) {
ret = ret.substr(0, totalLength-3) + "...";
}
return ret;
}
a pure css method base on -webkit-line-clamp:
@-webkit-keyframes ellipsis {/*for test*/_x000D_
0% { width: 622px }_x000D_
50% { width: 311px }_x000D_
100% { width: 622px }_x000D_
}_x000D_
.ellipsis {_x000D_
max-height: 40px;/* h*n */_x000D_
overflow: hidden;_x000D_
background: #eee;_x000D_
_x000D_
-webkit-animation: ellipsis ease 5s infinite;/*for test*/_x000D_
/**_x000D_
overflow: visible;_x000D_
/**/_x000D_
}_x000D_
.ellipsis .content {_x000D_
position: relative;_x000D_
display: -webkit-box;_x000D_
-webkit-box-orient: vertical;_x000D_
-webkit-box-pack: center;_x000D_
font-size: 50px;/* w */_x000D_
line-height: 20px;/* line-height h */_x000D_
color: transparent;_x000D_
-webkit-line-clamp: 2;/* max row number n */_x000D_
vertical-align: top;_x000D_
}_x000D_
.ellipsis .text {_x000D_
display: inline;_x000D_
vertical-align: top;_x000D_
font-size: 14px;_x000D_
color: #000;_x000D_
}_x000D_
.ellipsis .overlay {_x000D_
position: absolute;_x000D_
top: 0;_x000D_
left: 50%;_x000D_
width: 100%;_x000D_
height: 100%;_x000D_
overflow: hidden;_x000D_
_x000D_
/**_x000D_
overflow: visible;_x000D_
left: 0;_x000D_
background: rgba(0,0,0,.5);_x000D_
/**/_x000D_
}_x000D_
.ellipsis .overlay:before {_x000D_
content: "";_x000D_
display: block;_x000D_
float: left;_x000D_
width: 50%;_x000D_
height: 100%;_x000D_
_x000D_
/**_x000D_
background: lightgreen;_x000D_
/**/_x000D_
}_x000D_
.ellipsis .placeholder {_x000D_
float: left;_x000D_
width: 50%;_x000D_
height: 40px;/* h*n */_x000D_
_x000D_
/**_x000D_
background: lightblue;_x000D_
/**/_x000D_
}_x000D_
.ellipsis .more {_x000D_
position: relative;_x000D_
top: -20px;/* -h */_x000D_
left: -50px;/* -w */_x000D_
float: left;_x000D_
color: #000;_x000D_
width: 50px;/* width of the .more w */_x000D_
height: 20px;/* h */_x000D_
font-size: 14px;_x000D_
_x000D_
/**_x000D_
top: 0;_x000D_
left: 0;_x000D_
background: orange;_x000D_
/**/_x000D_
}
_x000D_
<div class='ellipsis'>_x000D_
<div class='content'>_x000D_
<div class='text'>text text text text text text text text text text text text text text text text text text text text text </div>_x000D_
<div class='overlay'>_x000D_
<div class='placeholder'></div>_x000D_
<div class='more'>...more</div>_x000D_
</div>_x000D_
</div>_x000D_
</div>
_x000D_
I've found this css (scss) solution that works quite well. On webkit browsers it shows the ellipsis and on other browsers it just truncates the text. Which is fine for my intended use.
$font-size: 26px;
$line-height: 1.4;
$lines-to-show: 3;
h2 {
display: block; /* Fallback for non-webkit */
display: -webkit-box;
max-width: 400px;
height: $font-size*$line-height*$lines-to-show; /* Fallback for non-webkit */
margin: 0 auto;
font-size: $font-size;
line-height: $line-height;
-webkit-line-clamp: $lines-to-show;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
An example by the creator: http://codepen.io/martinwolf/pen/qlFdp
Here is the closest solution I could get using just css.
<div class="ellipsis"> <span>...</span>
Hello this is Mr_Green from Stackoverflow. I love CSS. I live in CSS and I will never leave working on CSS even my work is on other technologies.</div>
div {
height: 3em;
line-height: 1.5em;
width: 80%;
border: 1px solid green;
overflow: hidden;
position: relative;
}
div:after {
content:". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .";
background-color: white;
color: white;
display: inline;
position: relative;
box-shadow: 8px 1px 1px white;
z-index: 1;
}
span {
position: absolute;
bottom: 0px;
right: 0px;
background-color: white;
}
I hope now some css expert would have got idea on how to make it perfect. :)
I have hacked around until I've managed to achieve something close to this. It comes with a few caveats:
I should also note that the text will be broken at a word boundary, not a character boundary. This was deliberate (since I consider that better for longer texts), but because it's different from what text-overflow: ellipsis
does, I thought I should mention it.
If you can live with these caveats, the HTML looks like this:
<div class="ellipsify">
<div class="pre-dots"></div>
<div class="dots">…</div>
<!-- your text here -->
<span class="hidedots1"></span>
<div class="hidedots2"></div>
</div>
And this is the corresponding CSS, using the example of a 150 pixel wide box with three lines of text on a white background. It assumes you have a CSS reset or similar that sets margins and paddings to zero where necessary.
/* the wrapper */
.ellipsify {
font-size:12px;
line-height:18px;
height: 54px; /* 3x line height */
width: 150px;
overflow: hidden;
position: relative; /* so we're a positioning parent for the dot hiders */
background: white;
}
/* Used to push down .dots. Can't use absolute positioning, since that
would stop the floating. Can't use relative positioning, since that
would cause floating in the wrong (namely: original) place. Can't
change height of #dots, since it would have the full width, and
thus cause early wrapping on all lines. */
.pre-dots {
float: right;
height: 36px; /* 2x line height (one less than visible lines) */
}
.dots {
float: right; /* to make the text wrap around the dots */
clear: right; /* to push us below (not next to) .pre-dots */
}
/* hides the dots if the text has *exactly* 3 lines */
.hidedots1 {
background: white;
width: 150px;
height: 18px; /* line height */
position: absolute; /* otherwise, because of the width, it'll be wrapped */
}
/* hides the dots if the text has *less than* 3 lines */
.hidedots2 {
background: white;
width: 150px;
height: 54px; /* 3x line height, to ensure hiding even if empty */
position: absolute; /* ensures we're above the dots */
}
The result looks like this:
To clarify how it works, here's the same image, except that .hidedots1
is hightlighted in red, and .hidedots2
in cyan. These are the rectangles that hide the ellipsis when there's no invisible text:
Tested in IE9, IE8 (emulated), Chrome, Firefox, Safari, and Opera. Does not work in IE7.
After looking over the W3 spec for text-overflow, I don't think this is possible using only CSS. Ellipsis is a new-ish property, so it probably hasn't received much usage or feedback as of yet.
However, this guy appears to have asked a similar (or identical) question, and someone was able to come up with a nice jQuery solution. You can demo the solution here: http://jsfiddle.net/MPkSF/
If javascript is not an option, I think you may be out of luck...
Source: Stackoverflow.com