如果内容太宽,则在 HTML 标签中插入省略号 (...)

IT技术 javascript html ellipsis elasticlayout
2021-01-24 13:58:19

我有一个具有弹性布局的网页,如果调整浏览器窗口的大小,它会改变其宽度。

在此布局中,标题 ( h2) 的长度可变(实际上是我无法控制的博客文章的标题)。目前 - 如果它们比窗口宽 - 它们被分成两行。

是否有一个优雅的、经过测试的(跨浏览器)解决方案 - 例如使用 jQuery - 缩短该标题标签的innerHTML并添加“...”如果文本太宽而无法在当前屏幕上放入一行/容器宽度?

6个回答

以下用于在单行上截断文本的仅 CSS 解决方案适用于http://www.caniuse.com 上列出的所有浏览器,但 Firefox 6.0 除外。请注意,除非您需要支持换行多行文本或更早版本的 Firefox,否则完全不需要 JavaScript。

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

如果您需要对 Firefox 早期版本的支持,请查看我在另一个问题上的回答

JS Fiddle 对于那些想要在浏览器上进行采样的人 - jsfiddle.net/r39Ad
2021-03-29 13:58:19
这比 jQuery 方法快几个数量级。在 IE7+ 和 Chrome 中工作正常。
2021-03-30 13:58:19
@DilipRajkumar 你需要提供更多细节,例如一个 JSFiddle例子来证明它在 IE 8 中不起作用。
2021-04-04 13:58:19
这也适用于古老的浏览器。我们在 2004 年左右在 Google 上成功地使用了它,当时我们需要在一些真正极端情况下的浏览器上优雅地支持或降级。
2021-04-06 13:58:19
@SharpCoder 你没有。文本截断的位置由包含它的元素的宽度决定,即当它溢出元素的宽度时它会被截断。
2021-04-08 13:58:19

我有一个在 FF3、Safari 和 IE6+ 中使用单行和多行文本的解决方案

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

.ellipsis.multiline {
    white-space: normal;
}

<div class="ellipsis" style="width: 100px; border: 1px solid black;">Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div class="ellipsis multiline" style="width: 100px; height: 40px; border: 1px solid black; margin-bottom: 100px">Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>

<script type="text/javascript" src="/js/jquery.ellipsis.js"></script>
<script type="text/javascript">
$(".ellipsis").ellipsis();
</script>

jquery.省略号.js

(function($) {
    $.fn.ellipsis = function()
    {
        return this.each(function()
        {
            var el = $(this);

            if(el.css("overflow") == "hidden")
            {
                var text = el.html();
                var multiline = el.hasClass('multiline');
                var t = $(this.cloneNode(true))
                    .hide()
                    .css('position', 'absolute')
                    .css('overflow', 'visible')
                    .width(multiline ? el.width() : 'auto')
                    .height(multiline ? 'auto' : el.height())
                    ;

                el.after(t);

                function height() { return t.height() > el.height(); };
                function width() { return t.width() > el.width(); };

                var func = multiline ? height : width;

                while (text.length > 0 && func())
                {
                    text = text.substr(0, text.length - 1);
                    t.html(text + "...");
                }

                el.html(t.html());
                t.remove();
            }
        });
    };
})(jQuery);
要提高性能,请执行二分搜索,而不是在“while”循环中一次删除 1 个字符。如果 100% 的文本不适合,请尝试 50% 的文本;如果 50% 适合,则为 75% 的文本,如果 50% 不适合,则为 25%,等等。
2021-03-21 13:58:19
很好,我一直在寻找如何处理多行溢出。一项改进:不是附加三个句点,而是附加省略号字符“...”。
2021-03-25 13:58:19
尽管在 IE 中,如果省略号函数应用于只有链接的 div,但在省略号后链接消失。关于这个的任何指示?
2021-04-05 13:58:19
这非常有效。您应该在 jQuery 站点上发布它。
2021-04-08 13:58:19
如果你想看到它的实际效果,你可以在这里看到它(抱歉插件代码的格式错误)jsfiddle.net/danesparza/TF6Rb/1
2021-04-10 13:58:19

我使用许多其他帖子构建了此代码,并进行了以下增强:

  1. 它使用二进制搜索来找到恰到好处的文本长度。
  2. 它通过设置一次性显示事件来处理省略号元素最初被隐藏的情况,该事件在第一次显示项目时重新运行省略号代码。这对于最初未显示某些项目的主从视图或树视图非常方便。
  3. 它可以选择添加带有原始文本的标题属性,以实现悬停效果。
  4. 添加display: block到样式中,因此跨工作
  5. 它使用省略号字符而不是 3 个句点。
  6. 它自动运行脚本以使用 .ellipsis 类

CSS:

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

.ellipsis.multiline {
        white-space: normal;
}

jquery.省略号.js

(function ($) {

    // this is a binary search that operates via a function
    // func should return < 0 if it should search smaller values
    // func should return > 0 if it should search larger values
    // func should return = 0 if the exact value is found
    // Note: this function handles multiple matches and will return the last match
    // this returns -1 if no match is found
    function binarySearch(length, func) {
        var low = 0;
        var high = length - 1;
        var best = -1;
        var mid;

        while (low <= high) {
            mid = ~ ~((low + high) / 2); //~~ is a fast way to convert something to an int
            var result = func(mid);
            if (result < 0) {
                high = mid - 1;
            } else if (result > 0) {
                low = mid + 1;
            } else {
                best = mid;
                low = mid + 1;
            }
        }

        return best;
    }

    // setup handlers for events for show/hide
    $.each(["show", "toggleClass", "addClass", "removeClass"], function () {

        //get the old function, e.g. $.fn.show   or $.fn.hide
        var oldFn = $.fn[this];
        $.fn[this] = function () {

            // get the items that are currently hidden
            var hidden = this.find(":hidden").add(this.filter(":hidden"));

            // run the original function
            var result = oldFn.apply(this, arguments);

            // for all of the hidden elements that are now visible
            hidden.filter(":visible").each(function () {
                // trigger the show msg
                $(this).triggerHandler("show");
            });

            return result;
        };
    });

    // create the ellipsis function
    // when addTooltip = true, add a title attribute with the original text
    $.fn.ellipsis = function (addTooltip) {

        return this.each(function () {
            var el = $(this);

            if (el.is(":visible")) {

                if (el.css("overflow") === "hidden") {
                    var content = el.html();
                    var multiline = el.hasClass('multiline');
                    var tempElement = $(this.cloneNode(true))
                        .hide()
                        .css('position', 'absolute')
                        .css('overflow', 'visible')
                        .width(multiline ? el.width() : 'auto')
                        .height(multiline ? 'auto' : el.height())
                    ;

                    el.after(tempElement);

                    var tooTallFunc = function () {
                        return tempElement.height() > el.height();
                    };

                    var tooWideFunc = function () {
                        return tempElement.width() > el.width();
                    };

                    var tooLongFunc = multiline ? tooTallFunc : tooWideFunc;

                    // if the element is too long...
                    if (tooLongFunc()) {

                        var tooltipText = null;
                        // if a tooltip was requested...
                        if (addTooltip) {
                            // trim leading/trailing whitespace
                            // and consolidate internal whitespace to a single space
                            tooltipText = $.trim(el.text()).replace(/\s\s+/g, ' ');
                        }

                        var originalContent = content;

                        var createContentFunc = function (i) {
                            content = originalContent.substr(0, i);
                            tempElement.html(content + "…");
                        };

                        var searchFunc = function (i) {
                            createContentFunc(i);
                            if (tooLongFunc()) {
                                return -1;
                            }
                            return 0;
                        };

                        var len = binarySearch(content.length - 1, searchFunc);

                        createContentFunc(len);

                        el.html(tempElement.html());

                        // add the tooltip if appropriate
                        if (tooltipText !== null) {
                            el.attr('title', tooltipText);
                        }
                    }

                    tempElement.remove();
                }
            }
            else {
                // if this isn't visible, then hook up the show event
                el.one('show', function () {
                    $(this).ellipsis(addTooltip);
                });
            }
        });
    };

    // ellipsification for items with an ellipsis
    $(document).ready(function () {
        $('.ellipsis').ellipsis(true);
    });

} (jQuery));
只是一个简短的说明...值得将 .css('max-width', 'none') 添加到 tempElement var ... 这样您就可以在 css 中使用 max-width 声明,使插件更加灵活(至少对于我拥有的大多数用例)。反正干得好。:)
2021-03-14 13:58:19
二分搜索更可取,但不适用于非常小的数据集,在这种情况下,与诸如 indexOf() 之类的直线搜索相比,它会降低性能……显然
2021-03-18 13:58:19
你能提供一个例子吗?我的问题在这里:stackoverflow.com/questions/26344520/...
2021-03-21 13:58:19
美丽的。为实现我的二分搜索建议而喝彩。
2021-03-28 13:58:19
这比上述接受的答案要快得多。如果你有多个 .ellipsis 元素,并且正在用它们做任何动态的事情,那么这个元素会表现得更好。
2021-03-29 13:58:19

以防万一你们都在 2013 年来到这里 - 这是我在这里找到的纯 css 方法:http : //css-tricks.com/snippets/css/truncate-string-with-ellipsis/

.truncate {
  width: 250px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

它运作良好。

FWIW,text-overflow不适用于textarea元素(截至 2015 年)。如果您需要支持,textarea您可以通过修改已接受的答案或使用它的这个分支来实现它
2021-04-02 13:58:19

我的回答只支持单行文本。查看下面 gfullam 对多行分叉的评论,它看起来很有希望。

我从第一个答案中重写了几次代码,我认为这应该是最快的。

它首先找到一个“估计”的文本长度,然后添加或删除一个字符,直到宽度正确。

它使用的逻辑如下所示:

在此处输入图片说明

找到“估计的”文本长度后,将添加或删除字符,直到达到所需的宽度。

我确定它需要一些调整,但这是代码:

(function ($) {
    $.fn.ellipsis = function () {
        return this.each(function () {
            var el = $(this);

            if (el.css("overflow") == "hidden") {
                var text = el.html().trim();
                var t = $(this.cloneNode(true))
                                        .hide()
                                        .css('position', 'absolute')
                                        .css('overflow', 'visible')
                                        .width('auto')
                                        .height(el.height())
                                        ;
                el.after(t);

                function width() { return t.width() > el.width(); };

                if (width()) {

                    var myElipse = "....";

                    t.html(text);

                    var suggestedCharLength = (text.length * el.width() / t.width()) - myElipse.length;

                    t.html(text.substr(0, suggestedCharLength) + myElipse);

                    var x = 1;
                    if (width()) {
                        while (width()) {
                            t.html(text.substr(0, suggestedCharLength - x) + myElipse);
                            x++;
                        }
                    }
                    else {
                        while (!width()) {
                            t.html(text.substr(0, suggestedCharLength + x) + myElipse);
                            x++;
                        }
                        x--;
                        t.html(text.substr(0, suggestedCharLength + x) + myElipse);
                    }

                    el.html(t.html());
                    t.remove();
                }
            }
        });
    };
})(jQuery);
我已经分叉了它以添加对 textareas 和多行(垂直)省略号截断的支持:jsfiddle.net/gfullam/j29z7381(顺便说一句,我喜欢近似逻辑)
2021-03-24 13:58:19
您的解决方案可能不是最好的,但已经很好地解释了。我喜欢这种类型的近似逻辑。+1 :)
2021-04-08 13:58:19