54

我需要"..."在可调整大小的元素内的文本中间实现省略号 ()。是它可能的样子。所以,

"Lorem ipsum dolor sit amet. Ut ornare dignissim ligula sed commodo."

变成

"Lorem ipsum dolor sit amet ... commodo."

当元素被拉伸到文本的宽度时,我希望省略号消失。如何才能做到这一点?

4

16 回答 16

36

在 HTML 中,将完整值放入自定义 data-* 属性中,例如

<span data-original="your string here"></span>

然后将事件侦听load器分配resize给一个 JavaScript 函数,该函数将读取原始数据属性并将其放置在innerHTML您的 span 标签中。以下是省略号函数的示例:

function start_and_end(str) {
  if (str.length > 35) {
    return str.substr(0, 20) + '...' + str.substr(str.length-10, str.length);
  }
  return str;
}

调整值,或者如果可能的话,使它们动态化,如果需要的话,对于不同的对象。如果你有来自不同浏览器的用户,你可以在你的 dom 中以相同的字体和大小从文本中窃取参考宽度。然后插入适当数量的字符以供使用。

提示也是在 ... 或 who 消息上有一个缩写标签,以使用户能够获得带有完整字符串的工具提示。

<abbr title="simple tool tip">something</abbr>
于 2009-05-06T20:46:23.583 回答
27

我想提出解决这个问题的我的例子。

主要思想是将文本分成两个偶数部分(或者第一个更大,如果长度是奇数),其中一个最后有省略号,另一个右对齐text-overflow: clip

因此,如果您想让 js 自动/通用,您需要做的就是拆分字符串并设置属性。

不过,它有一些缺点。

  1. 没有很好的文字包装,甚至是字母(text-overflow: ''目前仅在 FF 中有效)
  2. 如果单词之间发生分裂 - 空格应该在第一部分。否则,它会崩溃。
  3. 字符串的结尾不应该有任何感叹号,因为direction: rtl- 它们将被移动到字符串的左侧。我认为,可以通过将单词的右侧部分放入标签中并将感叹号放入::after伪元素中来解决此问题。但我还没有让它正常工作。

但是,有了所有这些,它对我来说真的很酷,尤其是当你拖动浏览器的边框时,你可以在 jsfiddle 页面上轻松地做到这一点:https ://jsfiddle.net/extempl/93ymy3oL/ 。或者只运行下面固定最大宽度的代码段。

剧透下的GIF:

动图

body {
  max-width: 400px;
}

span::before, span::after {
  display: inline-block;
  max-width: 50%;
  overflow: hidden;
  white-space: pre;
}

span::before {
  content: attr(data-content-start);
  text-overflow: ellipsis;
}

span::after {
  content: attr(data-content-end);
  text-overflow: '';
  direction: rtl;
}
<span data-content-start="Look deep into nature, and then you " 
      data-content-end=  "will understand everything better"></span>

<br>
<span data-content-start="https://www.google.com.ua/images/branding/g" 
      data-content-end=  "ooglelogo/2x/googlelogo_color_272x92dp.png"></span>

于 2016-04-07T08:15:27.257 回答
10

所以我的同事想出了一个不使用额外 dom 元素的解决方案。我们检查div是否溢出并添加最后n个字符的数据属性。其余的在 css 中完成。

这是一些HTML:

<div class="box">
    <div class="ellipsis" data-tail="some">This is my text it is awesome</div>
</div>
<div class="box">
    <div class="ellipsis">This is my text</div>
</div>

和CSS:

.box {
    width: 200px;
}

.ellipsis:before {
    float: right;
    content: attr(data-tail);
}

.ellipsis {
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

这是强制性的 jsfiddle:http: //jsfiddle.net/r96vB/1/

于 2014-06-05T00:04:15.517 回答
7

以下 Javascript 函数将执行中间截断,如 OS X:

function smartTrim(string, maxLength) {
    if (!string) return string;
    if (maxLength < 1) return string;
    if (string.length <= maxLength) return string;
    if (maxLength == 1) return string.substring(0,1) + '...';

    var midpoint = Math.ceil(string.length / 2);
    var toremove = string.length - maxLength;
    var lstrip = Math.ceil(toremove/2);
    var rstrip = toremove - lstrip;
    return string.substring(0, midpoint-lstrip) + '...' 
    + string.substring(midpoint+rstrip);
}       

它将用省略号替换中间的字符。我的单元测试显示:

var s = '1234567890';
assertEquals(smartTrim(s, -1), '1234567890');
assertEquals(smartTrim(s, 0), '1234567890');
assertEquals(smartTrim(s, 1), '1...');
assertEquals(smartTrim(s, 2), '1...0');
assertEquals(smartTrim(s, 3), '1...90');
assertEquals(smartTrim(s, 4), '12...90');
assertEquals(smartTrim(s, 5), '12...890');
assertEquals(smartTrim(s, 6), '123...890');
assertEquals(smartTrim(s, 7), '123...7890');
assertEquals(smartTrim(s, 8), '1234...7890');
assertEquals(smartTrim(s, 9), '1234...67890');
assertEquals(smartTrim(s, 10), '1234567890');
assertEquals(smartTrim(s, 11), '1234567890');
于 2009-05-06T20:31:07.927 回答
4

这可能有点晚了,但我一直在寻找解决方案,一位同事提出了一个非常优雅的解决方案,我将分享。它需要一些 JS,但不是很多。

想象一下div,您需要将标签放入以下尺寸:

<div style="width: 200px; overflow: hidden"></div>

现在,您有一个函数,它将接受两个参数:一个带有标签的字符串和一个 DOM 元素(this div)以适应它:

function setEllipsisLabel(div, label) 

您要做的第一件事是span使用此标签创建一个,并将其放入div

var span = document.createElement('span');
span.appendChild(document.createTextNode(label));
span.style.textOverflow = 'ellipsis';
span.style.display = 'inline-block';
div.appendChild(span);

我们将该text-overflow属性设置为“省略号”,以便在文本被截断时,在末尾添加一个漂亮的“...”来说明这一点。我们还设置display为“inline-block”,以便这些元素具有我们以后可以操作的真实像素尺寸。到目前为止,没有什么是我们用纯 CSS 做不到的。

但是我们想要中间的省略号。首先,我们应该确定我们是否需要它......这可以通过比较div.clientWidth来完成 - 省略号仅在比 宽span.clientWidth时才需要。spandiv

如果我们确实需要省略号,让我们首先说我们希望在单词末尾显示固定数量的字符 - 比如说 10。所以让我们创建一个仅包含标签最后 10 个字符的跨度,并将其粘贴到分区:

var endSpan = document.createElement('span');
endSpan.style.display = 'inline-block';
endspan.appendChild(document.createTextNode(label.substring(label.length - 10)));
div.appendChild(endSpan);

现在,让我们覆盖原来的宽度span以适应新的宽度:

span.style.width = (div.clientWidth - endSpan.clientWidth) + 'px';

因此,我们现在有一个看起来像这样的 DOM 结构:

<div style="width: 200px; overflow: hidden">
   <span style="display: inline-block; text-overflow: ellipsis; width: 100px">
      A really long label is shown in this span
   </span>
   <span style="display: inline-block"> this span</span>
</div>

因为第一个spantext-overflow设置为“省略号”,所以它会在末尾显示“...”,然后是第二个跨度的 10 个字符,导致省略号大约显示在div.

您也不需要对 endSpan 的 10 个字符长度进行硬编码:这可以通过计算' 的初始宽度与span' 的初始宽度的比率来近似div,从标签的长度中减去适当的比例并除以 2。

于 2012-05-18T20:12:59.077 回答
3

你不能用 CSS 做到这一点。问题是 HTML 和 CSS 应该适用于各种浏览器和字体,几乎不可能以一致的方式计算字符串的宽度。这是一个可能对您有所帮助的想法。但是,您需要多次这样做,直到找到具有适当宽度的字符串。

于 2009-05-06T20:46:05.503 回答
3

在对 flex box 进行了一些研究之后,我发现了这个纯 CSS 解决方案,我认为它非常酷。

<div style="width:100%;border:1px solid green;display:inline-flex;flex-wrap:nowrap;">
   <div style="flex: 0 1 content;text-overflow: ellipsis;overflow:hidden;white-space:nowrap;"> Her comes very very very very very very very very very very very very very very very very very very very long </div>
   <div style="flex: 1 0 content;white-space:nowrap;"> &nbsp;but flexible line</div>
</div>
于 2016-06-09T09:51:59.447 回答
2

这是我能找到的最短的位,它将中间的 3 个字符替换为 ....

function shorten(s, max) {
  return s.length > max ? s.substring(0, (max / 2) - 1) + '...' + s.substring(s.length - (max / 2) + 2, s.length) : s
}
于 2017-10-05T21:35:14.873 回答
2

我在这里看到的所有解决方案都没有考虑到不同的字符具有不同的宽度。我的解决方案考虑到了这一点。基本上,它会删除一个字符的文本,直到它适合,看看:

const span = document.getElementById("span");
const div = document.getElementById("div");
const originalText = span.textContent;
const textLength = originalText.length;
let part1 = originalText.substr(0, Math.floor(textLength/2));
let part2 = originalText.substr(Math.floor(textLength/2));
let trimPart1 = true;
while (span.clientWidth > div.clientWidth) {
    if (trimPart1) {
    part1 = part1.substr(0, part1.length - 1);
  } else {
    part2 = part2.substr(-1 * (part2.length - 1));
  }
    span.textContent = part1 + "..." + part2;
  trimPart1 = !trimPart1;
}
<div id="div" style="overflow: hidden; width: 200px; white-space: nowrap;">
  <span id="span" style="display: inline-block">this is a quite long text that has some words and I want it to be split in half</span>
</div>

https://jsfiddle.net/maxim_mazurok/oujctpz8/56/

Mac 的 Finder 以同样的方式工作,它首先尝试剥离左侧部分,然后是右侧部分。所以,它可能有WWWW...WWWWW,就像我的解决方案一样。

虽然它不是最有效的。也许,同样可以使用虚拟 DOM 或画布来更好地优化性能。

于 2020-11-10T05:43:09.497 回答
1

该解决方案是上述解决方案的混合,并将最后一个完整的单词放在缩短文本的末尾。但是,如果最后一个单词长于可用空间的三分之一,它也会从左侧缩短。如果找到破折号(“-”),则将其从那里剪掉,如果没有,则将其剪掉。

function truncate(text, textLimit) {
    if (!text) return text;
    if (textLimit < 1) return string;
    if (text.length < textLimit) return text;
    if (textLimit === 1) return text.substring(0,1) + '...';
    /* extract the last word */
    var lastPart = text.slice( string.lastIndexOf(' ')+1 );
    /* if last word is longer then a third of the max available space
       cut it from the left */
    var lastPartLimit = Math.ceil(textLimit / 3);
    if(lastPart.length > lastPartLimit) {
        var truncatedLastPart = lastPart;
        /* Try to find a dash and cut the last word there */
        var lastDashPart = text.slice( text.lastIndexOf('-')+1 );
        if(lastDashPart.length < lastPartLimit){
            truncatedLastPart = lastDashPart;
        }
        /* If the last part is still to long or not available cut it anyway */
        if(truncatedLastPart.length > lastPartLimit) {
            var lastIndex = lastPart.length - lastPartLimit;
            truncatedLastPart = lastPart.substring( lastIndex );
        }
        lastPart = truncatedLastPart;
    }
    var dots = '... ';
    var firsPartLength = textLimit - lastPart.length - dots.length;
    return text.substring(0, firstPartLength) + dots + lastPart;
}

console.log( truncate("New York City", 10) ); // Ne... City (max of 10 characters)
console.log( truncate("New York Kindergarden", 14) ); // Ne...ergarden (max of 14 characters, last word gets cut from the left by a third)
console.log( truncate("New York Kinder-garden", 14) ); // Ne...garden (max of 14 characters, last word gets cut by the dash from the left)
于 2019-05-17T09:04:18.243 回答
1

这是我的看法——一个纯 CSS 的解决方案,遗憾的是现在只能在 Firefox 中使用:

div {
  width: 20em;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  text-overflow: " … is also your text.";
}
<div>Here's the long string of letters that accidentally is also your text.</div>

text-overflow如果需要动态文本,可以直接在元素上指定第二个声明。不支持这种语法的浏览器(Chrome,尤其是 :-)将回退到普通的旧省略号。

于 2021-07-16T10:14:53.587 回答
0

我刚刚创建了一个可以在中间、nearEnd 和 End 修剪但尚未测试的函数,因为我最终在服务器端需要它

//position acceptable values : middle, end, closeEnd
function AddElipsis(input, maxChars, position) {
    if (typeof input === 'undefined') {
        return "";
    }
    else if (input.length <= maxChars) {
        return input;
    }
    else {
        if (position == 'middle') {
            var midPos = Math.floor(maxChars / 2) - 2;
            return input.substr(0, midPos) + '...' + input.substr(input.length - midPos, input.length);
        }
        else if (position == 'closeEnd') {
            var firstPart = Math.floor(maxChars * 0.80) - 2;
            var endPart = Math.floor(maxChars * 0.20) - 2;
            return input.substr(0, firstPart) + '...' + input.substr(input.length - endPart, input.length);
        }
        else {
            return input.substr(0, maxChars - 3) + '...';
        }
    }
}
于 2014-10-30T08:36:10.363 回答
0

另一个刺:

function truncate( str, max, sep ) {
    max = max || 10;
    var len = str.length;
    if(len > max){
        sep = sep || "...";
        var seplen = sep.length;
        if(seplen > max) { return str.substr(len - max) }

        var n = -0.5 * (max - len - seplen);
        var center = len/2;
        return str.substr(0, center - n) + sep + str.substr(len - center + n);
    }
    return str;
}

console.log( truncate("123456789abcde") ); // 123...bcde (using built-in defaults) 
console.log( truncate("123456789abcde", 8) ); // 12...cde (max of 8 characters) 
console.log( truncate("123456789abcde", 12, "_") ); // 12345_9abcde (customize the separator) 
于 2015-06-03T07:32:15.080 回答
0

这将使您对省略号和占位符文本的位置有更多的控制:

function ellipsis(str, maxLength, ellipsisLocationPercentage,placeholder) {
    /*
    ARGUMENTS:
    str - the string you want to maninpulate
    maxLength -  max number of characters allowed in return string
    ellipsisLocationPercentage (optional) - How far (percentage wise) into the return string you want the ellipses to be placed
        Examples:
        .85 : This is a very long string. This is a very long string. This is a very long string. This is a ver[...]very long string.
        .25 : This is a very long string. [...]g. This is a very long string. This is a very long string. This is a very long string.
    placeholder (optional) - this will be used to replace the removed substring. Suggestions : '...', '[..]', '[ ... ]', etc....
    */
    if(ellipsisLocationPercentage == null || isNaN(ellipsisLocationPercentage) || ellipsisLocationPercentage >= 1 || ellipsisLocationPercentage <= 0){
        //we've got null or bad data.. default to something fun, like 85% (that's fun, right??)
        ellipsisLocationPercentage = .85;
    }
    if(placeholder == null || placeholder ==""){
        placeholder = "[...]";
    }

    if (str.length > (maxLength-placeholder.length)) {
        //get the end of the string
        var beginning = str.substr(0, (maxLength - placeholder.length)*ellipsisLocationPercentage );
        var end = str.substr(str.length-(maxLength - placeholder.length) * (1-ellipsisLocationPercentage));
        return beginning + placeholder + end;
    }
    return str;
}

你可以通过调用来调用这个函数:

ellipsis("This is a very long string. Be Scared!!!!", 8);//uses default values
ellipsis("This is a very long string. Be Scared!!!!", 8,.5);//puts ellipsis at half way point
ellipsis("This is a very long string. Be Scared!!!!", 8,.75,'<..>');//puts ellipsis at 75% of the way into the string and uses '<..>' as the placeholder
于 2015-08-26T18:40:10.857 回答
0

为了干净利落并在缩短文本的末尾有一个完整的单词,我使用了下面的函数。

function prepareText(text){
  var returnString = text;
  var textLimit = 35;
  if(text.length > textLimit){
    var lastWord = text.slice( text.lastIndexOf(' ')+1 );
    var indexFromEnd = lastWord.length;
    var ellipsis = '... ';

    returnString = text.slice(0, textLimit - indexFromEnd - ellipsis.length);
    returnString = returnString + ellipsis + lastWord;
  }
  return returnString;
}

$('#ex1Modified').html( prepareText( $('#ex1').html() ) );

$('#ex2Modified').html( prepareText( $('#ex2').html() ) );

$('#ex3Modified').html( prepareText( $('#ex3').html() ) );
body{color:#777; font-family: sans-serif;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h2>Shortened Quotes from Albert Einstein</h2>

<div id="ex1">"The true sign of intelligence is not knowledge but imagination."</div>
<div id="ex1Modified"></div>
<br>
<div id="ex2">"Look deep into nature, and then you will understand everything better."</div>
<div id="ex2Modified"></div>
<br>
<div id="ex3">"You can't blame gravity for falling in love."</div>
<div id="ex3Modified"></div>

于 2016-03-30T20:55:57.453 回答
0

这是一个优雅的解决方案:

function truncateMiddle(word) {
    const tooLongChars = 15; // arbitrary

    if (word.length < tooLongChars) {
        return word;
    }

    const ellipsis = '...';
    const charsOnEitherSide = Math.floor(tooLongChars / 2) - ellipsis.length;

    return word.slice(0, charsOnEitherSide) + ellipsis + word.slice(-charsOnEitherSide);
}
于 2019-09-13T19:09:30.197 回答