235

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?

Here's a demo.

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.

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
Tony Bogdanov
  • 7,436
  • 10
  • 49
  • 80
  • What determines "there is space"? Is everything including the font height in set pixels? What would happen if an end user increased the font size at their browser? – Joel Etherton Apr 09 '13 at 18:22
  • 1
    duplicate http://stackoverflow.com/questions/6222616/with-css-use-for-overflowed-block-of-multi-lines – Tom Apr 09 '13 at 18:23
  • @JoelEtherton I suppose that's up for the browser to decide and yes, everything is in pixels in my case. – Tony Bogdanov Apr 09 '13 at 18:26
  • This can be a good solution: http://stackoverflow.com/questions/6222616/with-css-use-for-overflowed-block-of-multi-lines – ivy Feb 28 '14 at 08:00
  • This is a really nice read http://hackingui.com/front-end/a-pure-css-solution-for-multiline-text-truncation/ – anandharshan Dec 04 '17 at 14:20

19 Answers19

377

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;
Jakub Kurdziel
  • 3,216
  • 2
  • 12
  • 22
pxthxk
  • 4,125
  • 2
  • 14
  • 13
92

Take a look at this pure css version: http://codepen.io/martinwolf/pen/qlFdp

h2 {
  display: -webkit-box;
  max-width: 400px;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}
<h2>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et.</h2>
Dolan
  • 313
  • 1
  • 4
  • 14
amcdnl
  • 8,470
  • 12
  • 63
  • 99
49

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.

(Click to View on CodePen)

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 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>

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!

http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/

mplungjan
  • 169,008
  • 28
  • 173
  • 236
dashard
  • 877
  • 1
  • 10
  • 17
  • 1
    I just clicked on your Codepen link on an Android phone and it worked in Firefox. What platform/browser is it not working in? – dashard Jan 28 '15 at 21:09
  • 1
    https://www.uploady.com/#!/download/kAwBXv1CqXg/PU68wrP6QzGgydlS I'm using chrome and there are no ellipsis in the preview. Keep on adding lines of text, nothing happens. After how many lines will it start showing ellipsis ? – coding_idiot Jan 29 '15 at 11:09
  • In the uploady link you posted, the text clearly had not yet overflowed the container. The text has to be too much for the fixed container to display before the ellipses will appear. Just keep adding text to see the effect. – dashard Jan 29 '15 at 12:07
  • @MarcosPérezGude -- doesn't surprise me. Alluded to that with >>"Of course, being a pure CSS solution means that it's also a pretty complicated one…"< – dashard Sep 11 '15 at 13:45
  • Another demo: https://codepen.io/thdoan/pen/wKmZyO – thdoan May 28 '23 at 02:18
25

Use 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;
Community
  • 1
  • 1
vikas verma
  • 371
  • 3
  • 7
14

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;
Rohit Suthar
  • 3,528
  • 1
  • 42
  • 48
anandharshan
  • 5,817
  • 4
  • 34
  • 33
5

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>
Youth overturn
  • 341
  • 5
  • 7
4

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 */
}
Vince
  • 544
  • 5
  • 15
  • `-webkit-line-clamp` does not work for IE11, Edge, or Firefox. – Gaʀʀʏ Dec 02 '16 at 16:17
  • @Garry, you are right, at the time you would have needed a JS fix, but it now works fine. https://caniuse.com/#search=webkit-line-clamp – Vince Oct 09 '19 at 10:58
2

In my angular app the following style worked for me to achieve ellipsis on the overflow of text on the second line:

 <div style="height:45px; overflow: hidden; position: relative;">
     <span class=" block h6 font-semibold clear" style="overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box; 
        line-height: 20px; /* fallback */
        max-height: 40px; /* fallback */
        -webkit-line-clamp: 2; /* number of lines to show */
        -webkit-box-orient: vertical;">
        {{ event?.name}} </span>
 </div>

Hope it helps someone.

Nodira
  • 656
  • 1
  • 9
  • 23
2

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;

Reference

Awais
  • 4,752
  • 4
  • 17
  • 40
1

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);
}
Nabil Kadimi
  • 10,078
  • 2
  • 51
  • 58
1

Restricting to few lines will work in almost all browsers, but an ellipsis(3 dots) will not be displayed in Firefox & IE. Demo - http://jsfiddle.net/ahzo4b91/1/

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; 
}
1

You can use a dissolved out effect instead of ellipsis, pure CSS and looks more professional:

    <div style="width: 293px; height:48px; overflow: hidden; ">
        More than two line of text goes here-More than two line of text goes here
    </div>
    <div style="position: relative; top: -24px; width: 293px; height:24px; 
             background: linear-gradient(90deg, rgba(255,0,0,0) 40%, rgba(255,255,255,1) 99%);">
    </div>

Here I have assumed your background color is white.

Mahan Lamei
  • 29
  • 1
  • 4
1

this 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 */

0
          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

jimmyNames
  • 155
  • 1
  • 3
  • 14
0

Here's a Material-UI faded text effect based on Mahan Lamei's suggestion:

Create the overlay style
const 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

0

There are 2 possible solutions. The one in the top answer and a new approach using the new line height unit - e.g. max-height: 3lh

Neither is perfect:

Webkit Line Clamp can truncate words with no ellipsis (except on the final line)

Max Line Height shows an ellipsis on all lines if needed but often omits the ellipsis on the final line (see snippet)

For short words with a wide container Webkit Line Clamp is best

For long words with a narrow container prefer the Max Line Height approach

.common {
  overflow: hidden;
  width: 100px;
  margin-bottom: 10px;
  background: cyan;
}

.webkit-line-clamp-3-lines {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

.max-height-3lh {
  max-height: 3lh;
  text-overflow: ellipsis;
}
<h4>Webkit Line Clamp</h4>

PASS
<div class="common webkit-line-clamp-3-lines">
  00000 11111 22222 33333 44444 55555 66666 77777 88888 99999
</div>

FAIL: words truncated with no ellipsis on lines 1 and 2
<div class="common webkit-line-clamp-3-lines">
  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
</div>

<h4>Max Line Height</h4>

FAIL: no ellipsis on line 3
<div class="common max-height-3lh">
  00000 11111 22222 33333 44444 55555 66666 77777 88888 99999
</div>

PASS
<div class="common max-height-3lh">
  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
</div>
danday74
  • 52,471
  • 49
  • 232
  • 283
-1

This is a total hack, but it works:

http://jsfiddle.net/2wPNg/

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.

Morgan Kay
  • 208
  • 2
  • 3
  • 18
  • 5
    This will not right solution because if content is smaller then also it add '...' in the end. Fiddle : http://jsfiddle.net/2wPNg/ – Sachin Nov 25 '13 at 06:59
-1

Here 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="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="myLongVerticalText">
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 class="myLongVerticalText">
One Line Lorem ipsum dolor sit amet.  
</div>
</body>
Matteo Conta
  • 1,423
  • 13
  • 17
  • If you downvote this solution, please explain why here, I'll appreciate it. – Matteo Conta Jul 12 '17 at 09:46
  • 1
    OP asked for CSS solution and you offered jQuery? – dashard Aug 07 '17 at 19:22
  • I missed that it was a strong requirement the absence of javascript, in my case the pure CSS solution presented rendering problems, the jQuery solution gave me more control over the final rendering and the ellipsis position. – Matteo Conta Aug 08 '17 at 08:55
  • Absolutely agree. In my answer I noted that this was infinitely easier to achieve with JS. – dashard Aug 08 '17 at 15:47
-3

Not sure what your target is, but do you want the text to come on the second line?

Here is your jsFiddle: http://jsfiddle.net/8kvWX/4/ just removed the following:

     white-space:nowrap;  

Im not sure if this is what your are looking for or not.

Regards,

Mee

Mee
  • 158
  • 7
  • 1
    He wants the ellipsis at the end of the second line, which is not that easy to do without JavaScript... – Marc Audet Apr 09 '13 at 18:44
  • Right, as I found another person asking to have the lines on the second line and his CSS was pretty much the same as yours but the class was pointing to a ul tag instead. Anyways, sorry Tony. I will have a look on it again and update my answer if I get successful. – Mee Apr 09 '13 at 20:36
  • well i think that the best solution is the one from @Itay Gal. As far as I saw that one is working. – Mee Apr 10 '13 at 15:58