Text overflow ellipsis on two lines
Matthew Harrington
I know you can use a combination of CSS rules to make text end with ellipsis (...) when it's time to overflow (get out of parent's bounds).
Is it possible (feel free to just say, no) to achieve the same effect, but let the text wrap on more than one line?
div { width: 300px; height: 42px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}As you can see, the text ends with ellipsis when it goes wider than the div's width. However, there is still enough space for the text to wrap on a second line and go on. This is interrupted by white-space: nowrap, which is required for the ellipsis to work.
Any ideas?
P.S.: No JS solutions, pure CSS if possible.
518 Answers
Easy CSS properties can do the trick. The following is for a three-line ellipsis.
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis; 7 Take a look at this pure css version:
display: -webkit-box;
max-width: 400px;
height: 109.2px;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.625; 5 I'm not sure if you have seen this article, but Chris Coyier's excellent CSS-Tricks.com posted a link to this a while back and it's a pure CSS solution that accomplishes exactly what you seek.
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-size: 100% 100%; /* 512x1 image,gradient for IE9. Transparent at 0% -> white at 50% -> white at 100%.*/ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAABCAMAAACfZeZEAAAABGdBTUEAALGPC/xhBQAAAwBQTFRF////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wDWRdwAAAP90Uk5TgsRjMZXhS30YrvDUP3Emow1YibnM9+ggOZxrBtpRRo94gxItwLOoX/vsHdA2yGgL8+TdKUK8VFufmHSGgAQWJNc9tk+rb5KMCA8aM0iwpWV6dwP9+fXuFerm3yMs0jDOysY8wr5FTldeoWKabgEJ8RATG+IeIdsn2NUqLjQ3OgBDumC3SbRMsVKsValZplydZpZpbJOQco2KdYeEe36BDAL8/vgHBfr2CvTyDu8R7esU6RcZ5ecc4+Af3iLcJSjZ1ivT0S/PMs3LNck4x8U7wz7Bv0G9RLtHuEq1TbJQr1OtVqqnWqRdoqBhnmSbZ5mXapRtcJGOc4t2eYiFfH9AS7qYlgAAARlJREFUKM9jqK9fEGS7VNrDI2+F/nyB1Z4Fa5UKN4TbbeLY7FW0Tatkp3jp7mj7vXzl+4yrDsYoVx+JYz7mXXNSp/a0RN25JMcLPP8umzRcTZW77tNyk63tdprzXdmO+2ZdD9MFe56Y9z3LUG96mcX02n/CW71JH6Qmf8px/cw77ZvVzB+BCj8D5vxhn/vXZh6D4uzf1rN+Cc347j79q/zUL25TPrJMfG/5LvuNZP8rixeZz/mf+vU+Vut+5NL5gPOeb/sd1dZbTs03hBuvmV5JuaRyMfk849nEM7qnEk6IHI8/qn049hB35QGHiv0yZXuMdkXtYC3ebrglcqvYxoj1muvC1nDlrzJYGbpcdHHIMo2FwYv+j3QAAOBSfkZYITwUAAAAAElFTkSuQmCC); 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> <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>Of course, being a pure CSS solution means that it's also a pretty complicated one, but it works cleanly and elegantly. I will assume that Javascript is out of the question because this is much easier to achieve (and arguably more degradable) with Javascript.
As an added bonus, there's a downloadable zip file of the complete process (if you want to understand it and all), but also a SASS mixin file so that you can fold it into your process easy-peasy.
Hope this helps!
4Use this if above is not working
display: -webkit-box; max-width: 100%; margin: 0 auto; -webkit-line-clamp: 2; /* autoprefixer: off */ -webkit-box-orient: vertical; /* autoprefixer: on */ overflow: hidden; text-overflow: ellipsis; 1 Css below should do the trick.
After the second line the, text will contain ...
line-height: 1em;
max-height: 2em;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2; 1 My solution reuses the one of amcdnl, but my fallback consist of using a height for the text container:
.my-caption h4 { display: -webkit-box; margin: 0 auto; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; height: 40px;/* Fallback for non-webkit */
} 2 It seems more elegant combining two classes. You can drop two-lines class if only one row need see:
.ellipse { white-space: nowrap; display:inline-block; overflow: hidden; text-overflow: ellipsis; } .two-lines { -webkit-line-clamp: 2; display: -webkit-box; -webkit-box-orient: vertical; white-space: normal; } .width{ width:100px; border:1px solid hotpink; } <span class='width ellipse'> some texts some texts some texts some texts some texts some texts some texts </span> <span class='width ellipse two-lines'> some texts some texts some texts some texts some texts some texts some texts </span> For those working in scss, you need to add !autoprefixer to the start of the comment so that it is preserved for postcss:
I faced that issue that's why posting it here
line-height: 1em;
max-height: 2em;
display: -webkit-box;
/*! autoprefixer: off */
-webkit-box-orient: vertical;
-webkit-line-clamp: 2; You can use a dissolved out effect instead of ellipsis, pure CSS and looks more professional:
<div> More than two line of text goes here-More than two line of text goes here </div> <div> </div>Here I have assumed your background color is white.
Base on an answer I saw in stackoveflow, I created this LESS mixin (use this link to generate the CSS code):
.max-lines(@lines: 3; @line-height: 1.2) { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: @lines; line-height: @line-height; max-height: @line-height * @lines;
}Usage
.example-1 { .max-lines();
}
.example-2 { .max-lines(3);
}
.example-3 { .max-lines(3, 1.5);
} Restricting to few lines will work in almost all browsers, but an ellipsis(3 dots) will not be displayed in Firefox & IE. Demo -
div {
width: 300px;
height: 2.8em;
line-height: 1.4em;
display: flex;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
} In my angular app the following style worked for me to achieve ellipsis on the overflow of text on the second line:
<div> <span> {{ event?.name}} </span> </div>Hope it helps someone.
1 text-overflow: ellipsis; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; line-height: 36px; max-height: 18px; -webkit-line-clamp: 2; -webkit-box-orient: vertical;I've found a combo of both line-clamp and line-height works :D
Here's a Material-UI faded text effect based on Mahan Lamei's suggestion:
Create the overlay styleconst useStyles = makeStyles((theme) => createStyles({ fadeText: { background: `linear-gradient( 180deg, #FFFFFF00, 0%, #FFFFFF06 30%, #FFFFFFFF 100%)`, pointerEvents: "none", } })
)Next overlay a gradient on a fixed-height nested Box component<Grid container justify="center"> <Grid item xs={8} sm={6} md={4}> <Box> <Box component="div" overflow="hidden" display="flex" flexDirection="column" fontFamily="Roboto" fontSize="body1.fontSize" fontWeight="fontWeightLight" textAlign="justify" height={['8rem']} > <Box display="flex"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </Box> </Box> <Box className={classes.fadeText} display="block" position="relative" top="-4rem" height="4rem" /> </Box> </Grid>
</Grid>Working demo: Codesandbox
MUI's default theme uses abbreviated CSS colors (#FFF) so if you want to set your gradients based on the current theme you will need to override them with the full six character variants.
Example: using theme to set the gradient (e.g. based on the light/dark theme):
const useStyles = makeStyles((theme: Theme) => createStyles({ fadeText: { background: `linear-gradient( 180deg, ${theme.palette.background.paper}00 0%, ${theme.palette.background.paper}06 30%, ${theme.palette.background.paper}FF 100%)` } })
)Edit: Updated to include Tony Bogdanov's suggestion
2this is the solution that works for me as I understand everyone desired result could be different.
display: -webkit-box;
min-height: 109.2px;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.625; /* as per desire */ This is a total hack, but it works:
div { width: 30%; float: left; margin-right: 2%; height: 94px; overflow: hidden; position: relative;
}
div:after { display: block; content: '...'; width: 1em; height: 1.5em; background: #fff; position: absolute; bottom: -6px; right: 0; }It does have problems.... it might cut off a letter awkwardly, and it will probably have some weird results on a responsive site.
1Here is a simple script to manage the ellipsis using jQuery. It inspects the real height of the element and it creates a hidden original node and a truncated node. When the user clicks it switches between the two versions.
One of the great benefits is that the "ellipsis" is near the last word, as expected.
If you use pure CSS solutions the three dots appears distant from the last word.
function manageShortMessages() { $('.myLongVerticalText').each(function () { if ($(this)[0].scrollHeight > $(this)[0].clientHeight) $(this).addClass('ellipsis short'); }); $('.myLongVerticalText.ellipsis').each(function () { var original = $(this).clone().addClass('original notruncation').removeClass('short').hide(); $(this).after(original); //debugger; var shortText = ''; shortText = $(this).html().trim().substring(0, 60) + '...'; $(this).html(shortText); }); $('.myLongVerticalText.ellipsis').click(function () { $(this).hide(); if ($(this).hasClass('original')) { $(this).parent().find('.short').show(); } else { $(this).parent().find('.original').show(); } }); } manageShortMessages();div { border:1px solid red; margin:10px;
}
div.myLongVerticalText { height:30px; width:450px;
}
div.myLongVerticalText.ellipsis { cursor:pointer;
}
div.myLongVerticalText.original { display:inline-block; height:inherit;
}<script src=""></script>
<body>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sit amet quam hendrerit, sagittis augue vel, placerat erat. Aliquam varius porta posuere. Aliquam erat volutpat. Phasellus ullamcorper malesuada bibendum. Etiam fringilla, massa vitae pulvinar vehicula, augue orci mollis lorem, laoreet viverra massa eros id est. Phasellus suscipit pulvinar consectetur. Proin dignissim egestas erat at feugiat. Aenean eu consectetur erat. Nullam condimentum turpis eu tristique malesuada.
Aenean sagittis ex sagittis ullamcorper auctor. Sed varius commodo dui, nec consectetur ante condimentum et. Donec nec blandit mi, vitae blandit elit. Phasellus efficitur ornare est facilisis commodo. Donec convallis nunc sed mauris vehicula, non faucibus neque vehicula. Donec scelerisque luctus dui eu commodo. Integer eu quam sit amet dui tincidunt pharetra eu ac quam. Quisque tempus pellentesque hendrerit. Sed orci quam, posuere eu feugiat at, congue sed felis. In ut lectus gravida, volutpat urna vitae, cursus justo. Nam suscipit est ac accumsan consectetur. Donec rhoncus placerat metus, ut elementum massa facilisis eget. Donec at arcu ac magna viverra tincidunt.
</div>
<div>
One Line Lorem ipsum dolor sit amet.
</div>
</body> 4 Not sure what your target is, but do you want the text to come on the second line?
Here is your jsFiddle: just removed the following:
white-space:nowrap; Im not sure if this is what your are looking for or not.
Regards,
Mee
3