代码之家  ›  专栏  ›  技术社区  ›  SeaBass

将“…”放在可滚动的容器的末尾,但仅当滚动在顶部时

  •  0
  • SeaBass  · 技术社区  · 7 年前

    我正在寻找一种方法,有一个容器与垂直滚动,把“…”在文本的结尾,如果有更多的文本比可见区域。我发现了一个JS插件,但不是用于滚动容器。我试图修改它,但是当向下滚动时“…”会保留。而且看起来插件至少在FF中完全剪切了文本。我希望“…”只在你在容器顶部时可见。

    我已经为整个夹紧寻找了css解决方案,但是看起来( text-overflow: ellipsis )不能在多条线路上工作 white-space: nowrap ?

    /*!
    * Clamp.js 0.5.1
    *
    * Copyright 2011-2013, Joseph Schmitt http://joe.sh
    * Released under the WTFPL license
    * http://sam.zoy.org/wtfpl/
    */
    
    (function(){
        /**
         * Clamps a text node.
         * @param {HTMLElement} element. Element containing the text node to clamp.
         * @param {Object} options. Options to pass to the clamper.
         */
        function clamp(element, options) {
            options = options || {};
    
            var self = this,
                win = window,
                opt = {
                    clamp:              options.clamp || 2,
                    useNativeClamp:     typeof(options.useNativeClamp) != 'undefined' ? options.useNativeClamp : true,
                    splitOnChars:       options.splitOnChars || ['.', '-', '–', '—', ' '], //Split on sentences (periods), hypens, en-dashes, em-dashes, and words (spaces).
                    animate:            options.animate || false,
                    truncationChar:     options.truncationChar || '…',
                    truncationHTML:     options.truncationHTML
                },
    
                sty = element.style,
                originalText = element.innerHTML,
    
                supportsNativeClamp = typeof(element.style.webkitLineClamp) != 'undefined',
                clampValue = opt.clamp,
                isCSSValue = clampValue.indexOf && (clampValue.indexOf('px') > -1 || clampValue.indexOf('em') > -1),
                truncationHTMLContainer;
                
            if (opt.truncationHTML) {
                truncationHTMLContainer = document.createElement('span');
                truncationHTMLContainer.innerHTML = opt.truncationHTML;
            }
    
    
    // UTILITY FUNCTIONS __________________________________________________________
    
            /**
             * Return the current style for an element.
             * @param {HTMLElement} elem The element to compute.
             * @param {string} prop The style property.
             * @returns {number}
             */
            function computeStyle(elem, prop) {
                if (!win.getComputedStyle) {
                    win.getComputedStyle = function(el, pseudo) {
                        this.el = el;
                        this.getPropertyValue = function(prop) {
                            var re = /(\-([a-z]){1})/g;
                            if (prop == 'float') prop = 'styleFloat';
                            if (re.test(prop)) {
                                prop = prop.replace(re, function () {
                                    return arguments[2].toUpperCase();
                                });
                            }
                            return el.currentStyle && el.currentStyle[prop] ? el.currentStyle[prop] : null;
                        }
                        return this;
                    }
                }
    
                return win.getComputedStyle(elem, null).getPropertyValue(prop);
            }
    
            /**
             * Returns the maximum number of lines of text that should be rendered based
             * on the current height of the element and the line-height of the text.
             */
            function getMaxLines(height) {
                var availHeight = height || element.clientHeight,
                    lineHeight = getLineHeight(element);
    
                return Math.max(Math.floor(availHeight/lineHeight), 0);
            }
    
            /**
             * Returns the maximum height a given element should have based on the line-
             * height of the text and the given clamp value.
             */
            function getMaxHeight(clmp) {
                var lineHeight = getLineHeight(element);
                return lineHeight * clmp;
            }
    
            /**
             * Returns the line-height of an element as an integer.
             */
            function getLineHeight(elem) {
                var lh = computeStyle(elem, 'line-height');
                if (lh == 'normal') {
                    // Normal line heights vary from browser to browser. The spec recommends
                    // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
                    lh = parseInt(computeStyle(elem, 'font-size')) * 1.2;
                }
                return parseInt(lh);
            }
    
    
    // MEAT AND POTATOES (MMMM, POTATOES...) ______________________________________
            var splitOnChars = opt.splitOnChars.slice(0),
                splitChar = splitOnChars[0],
                chunks,
                lastChunk;
            
            /**
             * Gets an element's last child. That may be another node or a node's contents.
             */
            function getLastChild(elem) {
                //Current element has children, need to go deeper and get last child as a text node
                if (elem.lastChild.children && elem.lastChild.children.length > 0) {
                    return getLastChild(Array.prototype.slice.call(elem.children).pop());
                }
                //This is the absolute last child, a text node, but something's wrong with it. Remove it and keep trying
                else if (!elem.lastChild || !elem.lastChild.nodeValue || elem.lastChild.nodeValue == '' || elem.lastChild.nodeValue == opt.truncationChar) {
                    elem.lastChild.parentNode.removeChild(elem.lastChild);
                    return getLastChild(element);
                }
                //This is the last child we want, return it
                else {
                    return elem.lastChild;
                }
            }
            
            /**
             * Removes one character at a time from the text until its width or
             * height is beneath the passed-in max param.
             */
            function truncate(target, maxHeight) {
                if (!maxHeight) {return;}
                
                /**
                 * Resets global variables.
                 */
                function reset() {
                    splitOnChars = opt.splitOnChars.slice(0);
                    splitChar = splitOnChars[0];
                    chunks = null;
                    lastChunk = null;
                }
                
                var nodeValue = target.nodeValue.replace(opt.truncationChar, '');
                
                //Grab the next chunks
                if (!chunks) {
                    //If there are more characters to try, grab the next one
                    if (splitOnChars.length > 0) {
                        splitChar = splitOnChars.shift();
                    }
                    //No characters to chunk by. Go character-by-character
                    else {
                        splitChar = '';
                    }
                    
                    chunks = nodeValue.split(splitChar);
                }
                
                //If there are chunks left to remove, remove the last one and see if
                // the nodeValue fits.
                if (chunks.length > 1) {
                    // console.log('chunks', chunks);
                    lastChunk = chunks.pop();
                    // console.log('lastChunk', lastChunk);
                    applyEllipsis(target, chunks.join(splitChar));
                }
                //No more chunks can be removed using this character
                else {
                    chunks = null;
                }
                
                //Insert the custom HTML before the truncation character
                if (truncationHTMLContainer) {
                    target.nodeValue = target.nodeValue.replace(opt.truncationChar, '');
                    element.innerHTML = target.nodeValue + ' ' + truncationHTMLContainer.innerHTML + opt.truncationChar;
                }
    
                //Search produced valid chunks
                if (chunks) {
                    //It fits
                    if (element.clientHeight <= maxHeight) {
                        //There's still more characters to try splitting on, not quite done yet
                        if (splitOnChars.length >= 0 && splitChar != '') {
                            applyEllipsis(target, chunks.join(splitChar) + splitChar + lastChunk);
                            chunks = null;
                        }
                        //Finished!
                        else {
                            return element.innerHTML;
                        }
                    }
                }
                //No valid chunks produced
                else {
                    //No valid chunks even when splitting by letter, time to move
                    //on to the next node
                    if (splitChar == '') {
                        applyEllipsis(target, '');
                        target = getLastChild(element);
                        
                        reset();
                    }
                }
                
                //If you get here it means still too big, let's keep truncating
                if (opt.animate) {
                    setTimeout(function() {
                        truncate(target, maxHeight);
                    }, opt.animate === true ? 10 : opt.animate);
                }
                else {
                    return truncate(target, maxHeight);
                }
            }
            
            function applyEllipsis(elem, str) {
                elem.nodeValue = str + opt.truncationChar;
            }
    
    
    // CONSTRUCTOR ________________________________________________________________
    
            if (clampValue == 'auto') {
                clampValue = getMaxLines();
            }
            else if (isCSSValue) {
                clampValue = getMaxLines(parseInt(clampValue));
            }
    
            var clampedText;
            if (supportsNativeClamp && opt.useNativeClamp) {
                sty.overflow = 'hidden';
                sty.textOverflow = 'ellipsis';
                sty.webkitBoxOrient = 'vertical';
                sty.display = '-webkit-box';
                sty.webkitLineClamp = clampValue;
    
                if (isCSSValue) {
                    sty.height = opt.clamp + 'px';
                }
            }
            else {
                var height = getMaxHeight(clampValue);
                if (height <= element.clientHeight) {
                    clampedText = truncate(getLastChild(element), height);
                }
            }
            
            return {
                'original': originalText,
                'clamped': clampedText
            }
        }
    
        window.$clamp = clamp;
    })();
    
    var module = document.querySelector(".box p");
    $clamp(module, {clamp: 3});
    body {
      align-items: center;
      background: 
        radial-gradient(
          farthest-side at bottom left,
          rgba(255, 0, 255, 0.5), 
          #246756
        ),
        radial-gradient(
          farthest-corner at bottom right,
          rgba(255, 50, 50, 0.5), 
          #246756 400px
        );
      display: flex;
      height: 100vh;
      justify-content: center;
      line-height: 1.5;
    }
    
    .box {
      background-color: #fff;
      box-shadow: 2px 2px 10px #246756;
      padding: 2em;
      width: 200px;
    }
    .box p {
      overflow: scroll !important;
      max-height: 100px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="box">
      <p>Hey, don't cut me off like that. I want to speak my mind and don't appreciate being put into a box. More text coming here and here and here and here and here.</p>
    </div>
    3 回复  |  直到 7 年前
        1
  •  0
  •   Disfigure    7 年前

    我想你应该走这条路。只要看看你想要的高度就行了。

    var textEllipsisMultiline = function (element) {
        var wordArray = element.innerText.split(' ');
        while (element.scrollHeight > element.offsetHeight) {
            wordArray.pop(); // Remove last item
            element.innerText = wordArray.join(' ') + '...';
        }
    };
    
    
    textEllipsisMultiline(document.querySelector('#paragraph'));
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <title>Text Ellipsis Multiline</title>
    </head>
    <body>
      <p id="paragraph" style="height: 75px">
      "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad mSed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"inima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
      </p>
    </body>
    </html>
        2
  •  0
  •   WilliamNHarvey    7 年前

    如果你没有滚动到顶部,让它夹在不合理的大量行上(超过你所拥有的行数)

    $(".box p").scroll(function(e) {
      if($(this).scrollTop() === 0)
        $clamp(module, {clamp: 3});
      else
        $clamp(module, {clamp: 9999999});
    });
    

    /*!
    * Clamp.js 0.5.1
    *
    * Copyright 2011-2013, Joseph Schmitt http://joe.sh
    * Released under the WTFPL license
    * http://sam.zoy.org/wtfpl/
    */
    
    (function(){
        /**
         * Clamps a text node.
         * @param {HTMLElement} element. Element containing the text node to clamp.
         * @param {Object} options. Options to pass to the clamper.
         */
        function clamp(element, options) {
            options = options || {};
    
            var self = this,
                win = window,
                opt = {
                    clamp:              options.clamp || 2,
                    useNativeClamp:     typeof(options.useNativeClamp) != 'undefined' ? options.useNativeClamp : true,
                    splitOnChars:       options.splitOnChars || ['.', '-', '–', '—', ' '], //Split on sentences (periods), hypens, en-dashes, em-dashes, and words (spaces).
                    animate:            options.animate || false,
                    truncationChar:     options.truncationChar || '…',
                    truncationHTML:     options.truncationHTML
                },
    
                sty = element.style,
                originalText = element.innerHTML,
    
                supportsNativeClamp = typeof(element.style.webkitLineClamp) != 'undefined',
                clampValue = opt.clamp,
                isCSSValue = clampValue.indexOf && (clampValue.indexOf('px') > -1 || clampValue.indexOf('em') > -1),
                truncationHTMLContainer;
                
            if (opt.truncationHTML) {
                truncationHTMLContainer = document.createElement('span');
                truncationHTMLContainer.innerHTML = opt.truncationHTML;
            }
    
    
    // UTILITY FUNCTIONS __________________________________________________________
    
            /**
             * Return the current style for an element.
             * @param {HTMLElement} elem The element to compute.
             * @param {string} prop The style property.
             * @returns {number}
             */
            function computeStyle(elem, prop) {
                if (!win.getComputedStyle) {
                    win.getComputedStyle = function(el, pseudo) {
                        this.el = el;
                        this.getPropertyValue = function(prop) {
                            var re = /(\-([a-z]){1})/g;
                            if (prop == 'float') prop = 'styleFloat';
                            if (re.test(prop)) {
                                prop = prop.replace(re, function () {
                                    return arguments[2].toUpperCase();
                                });
                            }
                            return el.currentStyle && el.currentStyle[prop] ? el.currentStyle[prop] : null;
                        }
                        return this;
                    }
                }
    
                return win.getComputedStyle(elem, null).getPropertyValue(prop);
            }
    
            /**
             * Returns the maximum number of lines of text that should be rendered based
             * on the current height of the element and the line-height of the text.
             */
            function getMaxLines(height) {
                var availHeight = height || element.clientHeight,
                    lineHeight = getLineHeight(element);
    
                return Math.max(Math.floor(availHeight/lineHeight), 0);
            }
    
            /**
             * Returns the maximum height a given element should have based on the line-
             * height of the text and the given clamp value.
             */
            function getMaxHeight(clmp) {
                var lineHeight = getLineHeight(element);
                return lineHeight * clmp;
            }
    
            /**
             * Returns the line-height of an element as an integer.
             */
            function getLineHeight(elem) {
                var lh = computeStyle(elem, 'line-height');
                if (lh == 'normal') {
                    // Normal line heights vary from browser to browser. The spec recommends
                    // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
                    lh = parseInt(computeStyle(elem, 'font-size')) * 1.2;
                }
                return parseInt(lh);
            }
    
    
    // MEAT AND POTATOES (MMMM, POTATOES...) ______________________________________
            var splitOnChars = opt.splitOnChars.slice(0),
                splitChar = splitOnChars[0],
                chunks,
                lastChunk;
            
            /**
             * Gets an element's last child. That may be another node or a node's contents.
             */
            function getLastChild(elem) {
                //Current element has children, need to go deeper and get last child as a text node
                if (elem.lastChild.children && elem.lastChild.children.length > 0) {
                    return getLastChild(Array.prototype.slice.call(elem.children).pop());
                }
                //This is the absolute last child, a text node, but something's wrong with it. Remove it and keep trying
                else if (!elem.lastChild || !elem.lastChild.nodeValue || elem.lastChild.nodeValue == '' || elem.lastChild.nodeValue == opt.truncationChar) {
                    elem.lastChild.parentNode.removeChild(elem.lastChild);
                    return getLastChild(element);
                }
                //This is the last child we want, return it
                else {
                    return elem.lastChild;
                }
            }
            
            /**
             * Removes one character at a time from the text until its width or
             * height is beneath the passed-in max param.
             */
            function truncate(target, maxHeight) {
                if (!maxHeight) {return;}
                
                /**
                 * Resets global variables.
                 */
                function reset() {
                    splitOnChars = opt.splitOnChars.slice(0);
                    splitChar = splitOnChars[0];
                    chunks = null;
                    lastChunk = null;
                }
                
                var nodeValue = target.nodeValue.replace(opt.truncationChar, '');
                
                //Grab the next chunks
                if (!chunks) {
                    //If there are more characters to try, grab the next one
                    if (splitOnChars.length > 0) {
                        splitChar = splitOnChars.shift();
                    }
                    //No characters to chunk by. Go character-by-character
                    else {
                        splitChar = '';
                    }
                    
                    chunks = nodeValue.split(splitChar);
                }
                
                //If there are chunks left to remove, remove the last one and see if
                // the nodeValue fits.
                if (chunks.length > 1) {
                    // console.log('chunks', chunks);
                    lastChunk = chunks.pop();
                    // console.log('lastChunk', lastChunk);
                    applyEllipsis(target, chunks.join(splitChar));
                }
                //No more chunks can be removed using this character
                else {
                    chunks = null;
                }
                
                //Insert the custom HTML before the truncation character
                if (truncationHTMLContainer) {
                    target.nodeValue = target.nodeValue.replace(opt.truncationChar, '');
                    element.innerHTML = target.nodeValue + ' ' + truncationHTMLContainer.innerHTML + opt.truncationChar;
                }
    
                //Search produced valid chunks
                if (chunks) {
                    //It fits
                    if (element.clientHeight <= maxHeight) {
                        //There's still more characters to try splitting on, not quite done yet
                        if (splitOnChars.length >= 0 && splitChar != '') {
                            applyEllipsis(target, chunks.join(splitChar) + splitChar + lastChunk);
                            chunks = null;
                        }
                        //Finished!
                        else {
                            return element.innerHTML;
                        }
                    }
                }
                //No valid chunks produced
                else {
                    //No valid chunks even when splitting by letter, time to move
                    //on to the next node
                    if (splitChar == '') {
                        applyEllipsis(target, '');
                        target = getLastChild(element);
                        
                        reset();
                    }
                }
                
                //If you get here it means still too big, let's keep truncating
                if (opt.animate) {
                    setTimeout(function() {
                        truncate(target, maxHeight);
                    }, opt.animate === true ? 10 : opt.animate);
                }
                else {
                    return truncate(target, maxHeight);
                }
            }
            
            function applyEllipsis(elem, str) {
                elem.nodeValue = str + opt.truncationChar;
            }
    
    
    // CONSTRUCTOR ________________________________________________________________
    
            if (clampValue == 'auto') {
                clampValue = getMaxLines();
            }
            else if (isCSSValue) {
                clampValue = getMaxLines(parseInt(clampValue));
            }
    
            var clampedText;
            if (supportsNativeClamp && opt.useNativeClamp) {
                sty.overflow = 'hidden';
                sty.textOverflow = 'ellipsis';
                sty.webkitBoxOrient = 'vertical';
                sty.display = '-webkit-box';
                sty.webkitLineClamp = clampValue;
    
                if (isCSSValue) {
                    sty.height = opt.clamp + 'px';
                }
            }
            else {
                var height = getMaxHeight(clampValue);
                if (height <= element.clientHeight) {
                    clampedText = truncate(getLastChild(element), height);
                }
            }
            
            return {
                'original': originalText,
                'clamped': clampedText
            }
        }
    
        window.$clamp = clamp;
    })();
    
    var module = document.querySelector(".box p");
    var _text = $(".box p").text();
    $(".box p").scroll(function(e) {
      if($(this).scrollTop() === 0)
        $clamp(module, {clamp: 3});
      else
        $clamp(module, {clamp: 9999999});
    });
    $clamp(module, {clamp: 3});
    body {
      align-items: center;
      background: 
        radial-gradient(
          farthest-side at bottom left,
          rgba(255, 0, 255, 0.5), 
          #246756
        ),
        radial-gradient(
          farthest-corner at bottom right,
          rgba(255, 50, 50, 0.5), 
          #246756 400px
        );
      display: flex;
      height: 100vh;
      justify-content: center;
      line-height: 1.5;
    }
    
    .box {
      background-color: #fff;
      box-shadow: 2px 2px 10px #246756;
      padding: 2em;
      width: 200px;
    }
    .box p {
      overflow: scroll !important;
      max-height: 100px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="box">
      <p>Hey, don't cut me off like that. I want to speak my mind and don't appreciate being put into a box. More text coming here and here and here and here and here.</p>
    </div>
        3
  •  0
  •   SeaBass    7 年前

    我找到了一个简单的css解决方案。不幸的是,它不允许滚动,但在我的情况下,如果不滚动就更好了。两个缺点是,你需要设置一个背景色来掩盖这些点,并且这些点在区域之外,但在我的情况下是有效的。我有数百个div,所以css对我来说是一个比js好得多的选择。

    /* styles for '...' */ 
    .block-with-text {
      /* hide text if it more than N lines  */
      overflow: hidden;
      /* for set '...' in absolute position */
      position: relative; 
      /* use this value to count block height */
      line-height: 1.2em;
      /* max-height = line-height (1.2) * lines max number (3) */
      max-height: 3.6em; 
      /* fix problem when last visible word doesn't adjoin right side  */
      text-align: justify;  
      /* place for '...' */
      margin-right: -1em;
      padding-right: 1em;
      width: 300px;
    }
    /* create the ... */
    .block-with-text:before {
      /* points in the end */
      content: '...';
      /* absolute position */
      position: absolute;
      /* set position to right bottom corner of block */
      right: 0;
      bottom: 0;
    }
    /* hide ... if we have text, which is less than or equal to max lines */
    .block-with-text:after {
      /* points in the end */
      content: '';
      /* absolute position */
      position: absolute;
      /* set position to right bottom corner of text */
      right: 0;
      /* set width and height */
      width: 1em;
      height: 1em;
      margin-top: 0.2em;
      /* bg color = bg color under block */
      background: white;
    }
    <p class="block-with-text">Long text on multiple rows. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ornare enim et egestas posuere. Curabitur mollis sapien a nunc interdum, pretium imperdiet lorem viverra. Praesent lacus neque, tempor a nibh eget, tincidunt consectetur urna. Ut ornare pellentesque tortor in consequat. Sed id faucibus nibh, ut molestie mauris. Maecenas auctor lorem felis, luctus dictum eros varius sit amet. Vestibulum volutpat commodo nisl nec mollis. Proin varius at turpis eget feugiat. Suspendisse maximus sit amet nulla nec rutrum. Integer non nibh a lorem blandit ullamcorper. Nam commodo neque tellus, id volutpat neque iaculis ut.
    
    Vivamus aucto</p>
    <p class="block-with-text">Small text on one row. Without dots.</p>
    <p class="block-with-text" style="width: 250px;">2.5 lines example:  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ornare enim.</p>