Search code examples
cssclamp

Fadeout last line of text if more than n lines


We need to show product titles on a maximum of 3 lines, and fade out the 3rd line only if the title breaks onto more than 3 lines.

What I tried so far to solve this is having a wrapper with a max-height of 3 lines, the title in it and a pseudo-element that overlays a fade-out (resp. fade-to-white) gradient.

.title:after {
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 75%, rgba(255, 255, 255, 1) 100%);
  content: '';
  width: 100%;
  height: 1.3rem;
  position: absolute;
  top: 2rem;
  left: 0;
}

Problem is, this happens irrespective of whether there's a 4th(+) line.

I created a JSFiddle: https://jsfiddle.net/nq4ratr7/5/

Goal of the fiddle-example would be to show all titles up to 3 lines without a fadeout, and fadeout on the 3rd line for the example that breaks onto 4 ("4 lines...").

For performance-reasons, no JS should be used. I'm well aware that it's easy with JS.


Solution

  • This requires a container with the overflow on. The overlay is inside the child and has it's height derived from calc(100% - (line-height × 3)) - which will yield either a negative number (which gets turned into 0 by the browser), 0, or the excess height. We then use a fixed height gradient with repeating-linear-gradient and move it up by (line-height).

    .holder {
        width: 275px;
    }
    
    .title {
        margin: 30px 0;
        max-height: 75px; /* line-height × 3 */
        overflow: hidden;
    }
    
    .title > h2 {
        position: relative;
        margin: 0;
        padding: 0;
        line-height: 25px;
        font-size: 18px;
    }
    
    .title > h2::after {
        content: '';
        display: block;
        position: absolute;
        right: 0;
        bottom: 0;
        left: 0;
        height: calc(100% - 75px); /* 100% - (line-height × 3) */
        transform: translateY(-25px); /* 0 - line-height */
        background: repeating-linear-gradient(rgba(255, 255, 255, 0), #ffffff 25px); /* line-height */
    }
    <div class="holder">
        <div class="title">
            <h2>1 line of text 1 line of text</h2>
        </div>
        <div class="title">
            <h2>2 lines of text 2 lines of text 2 lines of text 2 lines of text 2 lines of text</h2>
        </div>
        <div class="title">
            <h2>3 lines of text 3 lines of text 3 lines of text 3 lines of text 3 lines of text 3 lines of text 3 lines of text</h2>
        </div>
        <div class="title">
            <h2>4 lines of text 4 lines of text 4 lines of text 4 lines of text 4 lines of text 4 lines of text 4 lines of text 4 lines of text 4 lines of text 4 lines of text</h2>
        </div>
        <div class="title">
            <h2>5 lines of text 5 lines of text 5 lines of text 5 lines of text 5 lines of text 5 lines of text 5 lines of text 5 lines of text 5 lines of text 5 lines of text 5 lines of text 5 lines of text</h2>
        </div>
        <div class="title">
            <h2>6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text 6 lines of text</h2>
        </div>
    </div>