【问题标题】:Text-overflow ellipsis on left side左侧的文本溢出省略号
【发布时间】:2012-04-05 07:32:00
【问题描述】:

我有一个路径列表(由于没有更好的词,也许面包屑路径更好地描述了它们)。有些值太长而无法在其父项中显示,因此我使用text-overflow: ellipsis。问题是重要信息在右边,所以我希望省略号出现在左边。像这样的 ascii 艺术:

----------------------------
|first > second > third    |
|...second > third > fourth|
|...fifth > sixth > seventh|
----------------------------

请注意,第一行足够短,所以它保持左对齐,但其他两行太长,所以省略号出现在左侧。

我更喜欢纯 CSS 的解决方案,但如果无法避免,JS 也可以。如果该解决方案仅适用于 Firefox 和 Chrome 也可以。

编辑:此时,我正在寻找一种解决方法来解决 Chrome 中的错误,这些错误会在文档混合 RTL 和 LTR 时阻止它正确呈现。这就是我从一开始就真正需要的,只是我没有意识到。

【问题讨论】:

标签: javascript html css


【解决方案1】:

这样的 jsFiddle 怎么样?它使用方向、文本对齐和文本溢出来获取左侧的省略号。根据MDN 的说法,将来可能会使用left-overflow-type 值指定左侧的省略号,但它仍被认为是实验性的。

p {
  white-space: nowrap;
  overflow: hidden;
  /* "overflow" value must be different from "visible" */
  text-overflow: ellipsis;
  width: 170px;
  border: 1px solid #999;
  direction: rtl;
  text-align: left;
}
<p>first > second > third<br /> second > third > fourth > fifth > sixth<br /> fifth > sixth > seventh > eighth > ninth</p>​

【讨论】:

  • 这很接近。在 FF 中看起来不错,但在 Chrome 中它会使第二行和第三行错误。看起来只是在省略号前面加上剪辑,然后在右侧剪辑。
  • 解决方案是对的,但是Chrome有一个混合ltr和rtl文档的渲染bug。
  • 这非常接近,但是添加符号是行不通的。例如,添加“@”会导致在左侧添加“@”,并在“@”符号的左侧添加更多文本。大多数符号似乎都会导致此问题(仅在 chrome 中测试)。
  • @Luke 和@robsonrosa 你可以在他们前面加上‎ as discssed here
  • 要补充@AntalOvc 所说的内容,您还可以进行RTL“嵌入”以影响整个序列。添加‪ 似乎可以很好地解决问题。
【解决方案2】:

根据您的编辑:

此时我正在寻找解决 Chrome 错误的方法 当文档混合 RTL 时阻止它正确呈现 和 LTR。这就是我从一开始就真正需要的,我只是没有 意识到这一点。

您是否查看过unicode-bidi css 属性(请参阅Sitepoint 或W3C)?实际上,我自己刚刚在another recent post 上了解到这一点。我的猜测是,您可能希望将embed 值用于那些与主站点相反方向的部分。因此,在 j08691 的答案中 direction: rtl 将 unicode-bidi: embed 添加到 CSS 中。这应该可以解决您遇到的“混合 RTL 和 LTR”问题。

【讨论】:

  • 我对此寄予厚望,但我尝试了 unicode-bidi here 并没有运气。
  • 对不起。根据日期 on this(2008 年顶部,2011 年底部),Chrome 中存在一段时间的问题(rtl 和 ellipsis)。它几乎看起来好像已经解决了,然后可能重新浮出水面,但很难说。
  • @ScottS 肯定有一个错误,这里提交的问题:code.google.com/p/chromium/issues/detail?id=155836
【解决方案3】:

这有点马车,但也许是正确的方向

http://jsfiddle.net/HerrSerker/ZfbaD/50/

$('.container')
    .animate({'width': 450}, 4000)
    .animate({'width': 100}, 4000)
    .animate({'width': 170}, 4000)
.container {  
  white-space: nowrap;                   
  overflow: hidden;              /* "overflow" value must be different from "visible" */   
  text-overflow: ellipsis;  
    width:170px;
    border:1px solid #999;
    direction:rtl;
}  
.container .part {
  direction:ltr;

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
    <span class="part">second</span> 
    <span class="part">&gt;</span> 
    <span class="part">third</span> 
    <span class="part">&gt;</span> 
    <span class="part">fourth</span> 
    <span class="part">&gt;</span> 
    <span class="part">fifth</span> 
    <span class="part">&gt;</span> 
    <span class="part">sixth</span>
</div>

【讨论】:

  • 这很接近。奇怪的是它如何在单词的开头添加省略号,但从末尾修剪单词。
【解决方案4】:

我将一些 JavaScript 放在一起以正则表达式输出三个项目,并在必要时添加省略号。这并没有明确查看框中可以容纳多少文本,但如果框是固定的,这可能不是问题。

<style>
p {  
    white-space: nowrap;                     
    overflow: hidden;
    text-overflow: ellipsis; 
    width:170px;
    border:1px solid #999;
    direction:rtl;
    text-align:left;
} 
</style>

<p>first &gt; second &gt; third<br />
second &gt; third &gt; fourth &gt; fifth &gt; sixth<br />
fifth &lt; sixth &lt; seventh &lt; eighth &lt; ninth</p>

<script>
    var text = $( 'p' ).text(),
        split = text.split( '\n' ),
        finalStr = '';
    for( i in split ){
        finalStr = finalStr.length > 0 ? finalStr + '<br />' : finalStr;
        var match = /(\w+\s?(<|>)?\s?){3}$/.exec( split[i] );
        finalStr = finalStr + ( split[i].length > match[0].length ? '...' : '' ) + match[0];
    }
    $( 'p' ).empty().html( finalStr );
</script>

【讨论】:

  • Js 可能是解决这个问题所必需的。我无法使用这个答案,因为我没有使用 jquery,而且我确信测量是必要的。
  • 省略号最好使用“\u2026”,而不是“...”
【解决方案5】:

我终于不得不在 JavaScript 中破解并做一些事情。我希望有人会想出一个 hail-mary CSS 解决方案,但人们似乎只是在投票支持 应该 如果不是因为 Chrome 错误,它应该是正确的答案。 j08691 可以为他的工作获得赏金。

<html>
    <head>
        <style>
            #container {
                width: 200px;
                border: 1px solid blue;
            }

            #container div {
                width: 100%;
                overflow: hidden;
                white-space: nowrap;
            }
        </style>
        <script>
            function trimRows() {

                var rows = document.getElementById('container').childNodes;
                for (var i=0, row; row = rows[i]; i++) {
                    if (row.scrollWidth > row.offsetWidth) {
                        var textNode = row.firstChild;
                        var value = '...' + textNode.nodeValue;
                        do {
                            value = '...' + value.substr(4);
                            textNode.nodeValue = value;

                        } while (row.scrollWidth > row.offsetWidth);
                    }
                }
            }
        </script>
    </head>
    <body onload='trimRows();'>
    <div id="container" >
        <div>first > second > third</div>
        <div>second > third > fourth > fifth > sixth</div>
        <div>fifth > sixth > seventh > eighth > ninth</div>​
    </div>
    </body>

</html>

Fiddle

【讨论】:

  • 我将您的解决方案更进一步,因此当被修剪的元素内部包含多个文本节点时它可以工作:jsfiddle.net/bgmort/qSyBU/3
  • 非常感谢布赖恩!我分叉了您的代码,因为我需要在开始时替换为“...”的内容,以及在调整窗口大小时,然后在窗口大小增加时将文本恢复为其初始状态。它可能不是最优雅的,但对于任何可能觉得它有用的人来说,这里是叉子:jsfiddle.net/sP9AE/1
  • 非常好,@Jimbo。现在也许有人可以将它抽象成一个 jQuery 插件。我可能会在某个时候这样做......
  • 你也可以试试trunk8或者jquery-truncate插件
  • 省略号最好使用“\u2026”,而不是“...”
【解决方案6】:

为什么不直接使用direction:rtl;

【讨论】:

  • 因为 RTL 和 LTR 混合时 Chrome 中的错误。
  • 这实际上应该是今天的答案。 RTL 现在工作得很好。在另一篇文章中查看此答案:stackoverflow.com/questions/34811197/…
  • 在 2022 年对此进行了测试,效果很好。我正在使用flex: row-reverse 更改容器中文本/图像的方向,我删除了 flex 并添加了方向,一切都一样 + 省略号现在在正确的一侧工作
【解决方案7】:

使用@Hemlocks、@Brian Mortenson 和@Jimbo 的解决方案,我构建了一个jQuery 插件来解决这个问题。

我还添加了对使用 .html() 返回初始值的支持,而不是让它返回当前的 innerHTML。希望它对某人有用...

(function($) {

$.trimLeft = function(element, options) {

    var trim = this;

    var $element = $(element), // reference to the jQuery version of DOM element
         element = element;    // reference to the actual DOM element

    var initialText = element.innerHTML;

    trim.init = function() {
        overrideNodeMethod("html", function(){ return initialText; });
        trimContents(element, element);
        return trim;
    };

    trim.reset = function(){
        element.innerHTML = initialText;
        return trim;
    };

    //Overide .html() to return initialText.
    var overrideNodeMethod = function(methodName, action) {
        var originalVal = $.fn[methodName];
        var thisNode = $element;
        $.fn[methodName] = function() {
            if (this[0]==thisNode[0]) {
                return action.apply(this, arguments);
            } else {
                return originalVal.apply(this, arguments);
            }
        };
    };

    var trimContents = function(row, node){
        while (row.scrollWidth > row.offsetWidth) {
            var childNode = node.firstChild;
            if (!childNode)
                return true;            
            if (childNode.nodeType == document.TEXT_NODE){
                trimText(row, node, childNode);
            }
            else {
                var empty = trimContents(row, childNode);
                if (empty){
                    node.removeChild(childNode);
                }
            }
        };
    };

    var trimText = function(row, node, textNode){
        var value = '\u2026' + textNode.nodeValue;
        do {
            value = '\u2026' + value.substr(4);
            textNode.nodeValue = value;
            if (value == '\u2026'){
                node.removeChild(textNode);
                return;
            }
        }
        while (row.scrollWidth > row.offsetWidth);
    };

    trim.init();

};

$.fn.trimLeft = (function(options){
  var othat = this;

  var single = function(that){
      if (undefined == $(that).data('trim')) {
          var trim = new $.trimLeft(that, options);
          $(that).data('trim', trim);
          $(window).resize(function(){
              $(that).each(function(){
                    trim.reset().init();
              });
          });
       }   
   };

   var multiple = function(){
        $(othat).each(function() {
            single(this);
        });
    };

    if($(othat).length>1)
        multiple(othat);            
    else
        single(othat);

    //-----------        
    return this;
});


})(jQuery);

开始使用:

//Call on elements with overflow: hidden and white-space: nowrap 
$('#container>div').trimLeft();
//Returns the original innerHTML
console.log($('#test').html());

fiddle

【讨论】:

    【解决方案8】:

    使用稍微复杂的标记(使用 bdi-tag 和省略号的额外跨度),我们可以在 CSS 中完全解决问题,根本不需要 JS——跨浏览器(IE、FF、Chrome)和包括将标点符号保留在右侧:

    http://jsbin.com/dodijuwebe/1/edit?html,css,output

    当然,这有点像 hack,涉及伪元素的优点。但是,我们的团队一直在生产中使用此代码,我们没有遇到任何问题。

    唯一需要注意的是:需要固定线的高度并且需要明确知道背景颜色(继承不起作用)。

    【讨论】:

      【解决方案9】:

      如果你不关心这些文本的索引,你可以使用这个方法(它反转文本行):

      如果您的文本中除了&lt;br&gt; 之外还有其他HTML 元素,则需要进行一些安排才能使用此方法。

      HTML 代码:

      <p>first > second > third<br/>
      second > third > fourth <br>
      fifth > sixth > seventh</p>
      

      CSS 代码:

      p{
        overflow: hidden;
        text-overflow: ellipsis;
        unicode-bidi: bidi-override;
        direction: rtl;
        text-align: left;
        white-space: nowrap;
        width: 140px;
      }
      

      JavaScript 代码

      [].forEach.call(document.getElementsByTagName("p"), function(item) {
      
        var str = item.innerText;
      
        //Change the operators
        str = str.replace(/[<>]/g, function(char){ return ({"<" : ">", ">" : "<"})[char] });
      
        //Get lines
        var lines = str.split(/\n/);
      
        //Reverse the lines
        lines = lines.map(function(l){ return l.split("").reverse().join("") }); 
      
        //Join the lines
        str = lines.join("<br>");
      
        item.innerHTML = str;
      
      });
      

      jsfiddle

      【讨论】:

        猜你喜欢
        • 2018-07-22
        • 1970-01-01
        • 2018-04-09
        • 2013-04-01
        • 2017-01-21
        • 2019-04-29
        • 2019-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多