Cross-browser multi-line text overflow with ellipsis appended within a fixed width and height

前端 未结 25 2464
栀梦
栀梦 2020-11-22 16:19

I made an image for this question to make it easier to understand.

Is it possible to create an ellipsis on a

with a fixed width and multiple
相关标签:
25条回答
  • 2020-11-22 16:37

    Here is a pure CSS way to accomplish this: http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/

    Here is a summary:

    enter image description here

    <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>
    
    0 讨论(0)
  • 2020-11-22 16:38

    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);
    
    0 讨论(0)
  • 2020-11-22 16:38

    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

    0 讨论(0)
  • 2020-11-22 16:39

    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.

    0 讨论(0)
  • 2020-11-22 16:39

    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

    0 讨论(0)
  • 2020-11-22 16:40

    Pure JS demo (without jQuery and 'while' loop)

    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);
    
    0 讨论(0)
提交回复
热议问题