CSS 在中间裁剪字符串

CSS crop string in the middle

我使用 css text-overflow: ellipsis.

裁剪了一个大文件名
<style>
   #fileName {
      width: 100px;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
  }
</style>
<div id="fileName"> This is the big name of my file.txt</div>

所以我有这个输出

This is the bi...

但我想保留文件扩展名并有这样的东西

This is the... le.txt

是否可以只使用 CSS?

由于我的文件始终是 txt,我尝试使用 text-overflow: string,但它似乎只适用于 Firefox:

 text-overflow: '*.txt';

这是我能想到的最好的...可能值得尝试清理第二个跨度的前缘...

CSS

#fileName span {
      white-space: nowrap;
      overflow: hidden;
      display:inline-block;
 }
#fileName span:first-child {
      width: 100px;
      text-overflow: ellipsis;
 }
#fileName span + span {
      width: 30px;
      direction:rtl;
      text-align:right;
 }

HTML

<div id="fileName">
    <span>This is the big name of my file.txt</span>
    <span>This is the big name of my file.txt</span>
</div>

http://jsfiddle.net/c8everqm/1/

JavaScript 选项:

var cropWithExtension = function(value, maxChars, trailingCharCount) {
    var result = value;

    if(value.length > maxChars){
        var front = value.substr(0, value.length - (maxChars - trailingCharCount - 3));
        var mid = "...";
        var end = value.substr(-trailingCharCount);

        result = front + mid + end;
    }

    return result;
}

var trimmedValue = cropWithExtension("This is the big file.txt", 21, 6);

这是一个干净的 CSS 解决方案,使用 data-* attribute 和两个 ::after 伪元素。我还添加了一个可选的悬停并显示所有文本(显示全文时需要删除 #fileName::after 伪元素)。

示例 1

#fileName {
  position: relative;
  width: 100px;
}

#fileName p {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

#fileName:after {
  content: attr(data-filetype);
  position: absolute;
  left: 100%;
  top: 0;
}


/*Show on hover*/

#fileName:hover {
  width: auto
}

#fileName:hover:after {
  display: none;
}
<div id="fileName" data-filetype="txt">
  <p>This is the big name of my file.txt</p>
</div>


更进一步——当文件名很短时隐藏附加的文件类型

#fileName p::after 被赋予了与文本背景相匹配的背景颜色。当文件名很短因此不会被 overflow: hidden.

截断时,这会覆盖“.txt”

注意 padding-right: 22px,这会将“.txt”推到省略号之外。

请参阅下面的示例 2 和 3,了解不同浏览器支持的不同方法。似乎不可能在所有浏览器中愉快地隐藏“.txt”。

示例 2

浏览器兼容性: Chrome 和 Firefox。

#fileName p::after 被赋予了与文本背景相匹配的背景颜色。当文件名很短因此不会被 overflow: hidden.

截断时,这会覆盖“.txt”

注意每个 ::after 伪元素上的 padding-rightpadding-right: 22px 将“.txt”推到省略号之外,padding-right: 100% 给出覆盖伪元素的宽度。 padding-right: 100% 不适用于 Edge 或 IE 11。

#fileName {
  position: relative;
  width: 122px;
}

#fileName::after {
  content: attr(data-filetype);
  position: absolute;
  right: 0;
  top: 0;
}

#fileName p {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  padding-right: 22px;
}

#fileName p::after {
  content: '';
  background: #FFF;
  position: relative;
  padding-right: 100%;
  z-index: 1;
}

/*Show on hover*/

#fileName:hover {
  width: auto;
}


/*Hide .txt on hover*/

#fileName:hover::after {
  display: none;
}
<div id="fileName" data-filetype=".txt">
  <p>This is the big name of my file.txt</p>
</div>

<div id="fileName" data-filetype=".txt">
  <p>Short.txt</p>
</div>

示例 3

浏览器兼容性: IE 11、Edge 和 Chrome。

#fileName p::after 上的 content: ... unholy amount of ... 赋予它宽度。这与 display: inline-block 一起是目前唯一适用于 Edge 浏览器/IE 11 以及 Chrome 的方法。 display: inline-block 在 Firefox 上打破了这个方法并且 .txt 不包含在短文件名中。

#fileName {
  position: relative;
  width: 122px;
}

#fileName::after {
  content: attr(data-filetype);
  position: absolute;
  right: 0;
  top: 0;
  padding-right: 10px; /*Fixes Edge Browser*/
}

#fileName p {
  white-space: nowrap;
  overflow: hidden;
  padding-right: 22px;
  text-overflow: ellipsis;
}

#fileName p::after {
  content: '.........................................................................................................................';/*Fixes Edge Browser*/
  background: #FFF;
  position: relative;
  display: inline-block;/*Fixes Edge Browser*/
  z-index: 1;
  color: #FFF;
}


/*Show on hover*/

#fileName:hover {
  width: auto
}

#fileName:hover::after {
  display: none;
}
<div id="fileName" data-filetype=".txt">
  <p>This is the big name of my file.txt</p>
</div>

<div id="fileName" data-filetype=".txt">
  <p>Short.txt</p>
</div>

对于适用于流动布局的解决方案,我想出了一些使用 flexbox 的东西。明显的缺点是需要三个元素。明显的优势:如果有足够的空间,所有内容都会显示出来。根据具体情况,可能需要为段落添加额外的 white-space 规则以及第一个跨度的最小宽度。

<p><span>Long text goes in here except for the</span><span>very end</span></p>

p {display:flex}
p span:first-child {flex-shrink:1; text-overflow: ellipsis; overflow: hidden}

附录:严格来说,flex-shrink 甚至不是必需的,因为它无论如何都是 flex-items 的默认行为。然而,在 IE10 中并非如此。在这种情况下,前缀也是必要的。

这是另一个对我很有效的建议:

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

输入---这是一个非常非常非常非常大的file.txt

要截断上面的文件名,请使用下面的 javascript

输出---这是一个非常...大的file.txt


var selectedFileName = getItemSelected();//Input

$scope.referenceFileName =getItemSelected();

var len = selectedFileName.length;

if(len > 30){
 selectedFileName = selectedFileName.substr(0,15)+'... '+selectedFileName.substr(len-15,15);    
}

$scope.fileName = selectedFileName;

**

Note:

**在json---后端传递$scope.referenceFileName

$scope.fileName 这将是---前端

这是一个使用 flexbox 的解决方案,并且是动态的(例如,当用户调整浏览器 window 大小时有效)。缺点是省略号后面的文字是固定大小的,不能把省略号放在正中间。

CSS

.middleEllipsis {
    margin: 10px;

    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: flex-start;
}
.start {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex-shrink: 1;
}
.end {
    white-space: nowrap;
    flex-basis: content;
    flex-grow: 0;
    flex-shrink: 0;

}

HTML

<div class="middleEllipsis">
    <div class="start">This is a really long file name, really long really long really long</div><div class="end">file name.txt</div>
</div>

在 jsfiddle 上调整 right-hand 边框的大小以查看效果:

https://jsfiddle.net/L9sy4dwa/1/

如果您愿意滥用 direction: rtl,您甚至可以将省略号放在文本中间,对您的 CSS:

做一些小改动
.middleEllipsis {
    margin: 10px;

    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: flex-start;
}
.middleEllipsis > .start {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex-shrink: 1;
}
.middleEllipsis > .end {
    white-space: nowrap;
    flex-basis: content;
    flex-grow: 0;
    flex-shrink: 1;
    align: right;
    overflow: hidden;
    direction: rtl;
}

您可以在 https://i.stack.imgur.com/CgW24.gif.

上看到这个样子的 gif 动画

这是一个展示这种方法的 jsfiddle:

https://jsfiddle.net/b8seyre3/

我尝试了其中一些 CSS 方法,但问题是如果文本很短,您将得到“short text short text”而不是“short text”。

所以我采用了 CSS + JS 方法。 JS(我编辑了 Jeremy Friesen 的以修复某些情况):

const shrinkString = (originStr, maxChars, trailingCharCount) => {
    let shrinkedStr = originStr;
    const shrinkedLength = maxChars - trailingCharCount - 3;
    if (originStr.length > shrinkedLength) {
      const front = originStr.substr(0, shrinkedLength);
      const mid = '...';
      const end = originStr.substr(-trailingCharCount);
      shrinkedStr = front + mid + end;
    }

    return shrinkedStr;
}

HTML:

<div>
  <h5>{shrinkString("can be very long of short text", 50, 15)}&nbsp;</h5>
</div>

CSS:

div {
  width: 200px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

希望对您有所帮助。对不起格式。这是我对 SO 的第一个回答。

接受答案很好。尽管对于浏览器兼容性,您可以检测是否截断。使整个 CSS 成为条件。

const wrap = document.getElementById('filenameText');
  if (wrap.offsetWidth >= wrap.scrollWidth) {
    this.truncation = false;
  }

 <div
    :data-filetype="data-filetype"
    :class="[truncation && 'truncateFilenamClass']"
  >

我发现 css 解决方案有很多错误且难以维护,因为您需要添加属性或元素来分隔文本。

我构建了一个非常简单的 Javascript 来处理它。发送您的文本和文本的最大长度,您会在中间截断文本。

const truncateMiddle = (text, maxCharacters) => {
  const txtLength = text.length; // Length of the incoming text
  const txtLengthHalf = maxCharacters ? Math.round(maxCharacters / 2) : Math.round(txtLength / 2); // set max txtHalfLength
  return text.substring(0, (txtLengthHalf -1)).trim() + '...' + text.substring((txtLength - txtLengthHalf) + 2, txtLength).trim() //Return the string
}

truncateMiddle('Once opon a time there was a little bunny', 10);

Returns: 一次...nny

缺点?当然,它需要更多功能才能响应。

CSS 很好,但我认为您必须在 JavaScript 之前完成以获得更准确的结果。 为什么? 因为,用 JS 你可以控制单词的第一个和最后一个文本的数量。 这只是 2 行 JavaScript 代码,用于按照您定义的方式裁剪字符串:-

    let fileName=document.getElementById('fileName')
    fileName.innerHTML=fileName.innerHTML.substring(1, 10)+'...'+fileName.innerHTML.slice(-2)
 <div id="fileName"> This is the big name of my file.txt</div>

此外,您可以根据需要选择第一个 n 个单词,而不是使用 JS 的前几个 letter/characters 个单词。 这是谁的JS代码:-

    let fileName=document.getElementById('fileName')
    let Words=fileName.innerHTML.split(" ")
    let i=0;
    fileName.innerHTML=''
    Words.forEach(e => {
        i++
        if(i<5)
        fileName.innerHTML+=e+' ' 
    });
    fileName.innerHTML+='...' 
 <div id="fileName"> This is the big name of my file.txt</div>