我在页面上有一个块元素的集合。它们都有CSS规则white-space, overflow, text-overflow设置,以便溢出的文本被修剪并使用省略号。

但是,并非所有元素都溢出。

有没有办法,我可以使用javascript来检测哪些元素溢出?

谢谢。

添加:示例HTML结构我正在工作。

<td><span>Normal text</span></td>
<td><span>Long text that will be trimmed text</span></td>

SPAN元素总是适合单元格,它们应用了省略号规则。我想检测何时将省略号应用于SPAN的文本内容。


当前回答

来自italo的回答非常好!不过,让我稍微细化一下:

function isEllipsisActive(e) {
   var tolerance = 2; // In px. Depends on the font you are using
   return e.offsetWidth + tolerance < e.scrollWidth;
}

跨浏览器兼容性

实际上,如果您尝试上面的代码并使用console.log打印出e.offsetWidth和e.scrollWidth的值,您将注意到,在IE上,即使您没有进行文本截断,也会出现1px或2px的值差异。

所以,根据你使用的字体大小,允许一定的容忍度!

其他回答

对于那些使用(或计划使用)来自Christian Varga的公认答案的人,请注意性能问题。

以这种方式克隆/操作DOM会导致DOM Reflow(请参阅此处关于DOM Reflow的解释),这是非常资源密集型的。

在一个页面上使用Christian Varga的100多个元素的解决方案会导致4秒的回流延迟,在此期间JS线程被锁定。考虑到JS是单线程的,这意味着对最终用户来说有很大的UX延迟。

Italo Borssatto的答案应该是公认的,在我的分析过程中,它大约快了10倍。

来自italo的回答非常好!不过,让我稍微细化一下:

function isEllipsisActive(e) {
   var tolerance = 2; // In px. Depends on the font you are using
   return e.offsetWidth + tolerance < e.scrollWidth;
}

跨浏览器兼容性

实际上,如果您尝试上面的代码并使用console.log打印出e.offsetWidth和e.scrollWidth的值,您将注意到,在IE上,即使您没有进行文本截断,也会出现1px或2px的值差异。

所以,根据你使用的字体大小,允许一定的容忍度!

我认为更好的检测方法是使用getClientRects(),似乎每个rect都有相同的高度,所以我们可以用不同的顶部值来计算行数。

getClientRects是这样工作的

function getRowRects(element) {
    var rects = [],
        clientRects = element.getClientRects(),
        len = clientRects.length,
        clientRect, top, rectsLen, rect, i;

    for(i=0; i<len; i++) {
        has = false;
        rectsLen = rects.length;
        clientRect = clientRects[i];
        top = clientRect.top;
        while(rectsLen--) {
            rect = rects[rectsLen];
            if (rect.top == top) {
                has = true;
                break;
            }
        }
        if(has) {
            rect.right = rect.right > clientRect.right ? rect.right : clientRect.right;
            rect.width = rect.right - rect.left;
        }
        else {
            rects.push({
                top: clientRect.top,
                right: clientRect.right,
                bottom: clientRect.bottom,
                left: clientRect.left,
                width: clientRect.width,
                height: clientRect.height
            });
        }
    }
    return rects;
}

getrowreck是这样工作的

你可以这样检测

在比较offsetWidth > scrollWidth时,上面的答案有一个小像素问题。

W3C有一个返回元素的遗留API。scrollWidth值被四舍五入,这导致比较在某些情况下返回false。 如果元素宽度为150px, scrollWidth为150.4px(四舍四入到150),那么即使浏览器在文本中显示省略号,该检查也将返回false。

他们已经尝试更新返回分数像素的api,但由于webcompat,它被恢复了。

有一个使用max-content和getClientRects()的变通方法。 这是一个示例代码,我使用onMouseEnter。 注意,这只在容器的边界为可用宽度的100%时才有效(因此,如果您使用flexbox,您的容器必须为flex: 1例如。

hasEllipsis(elementItem) {
    let scrollWidth = elementItem.scrollWidth;
    
    elementItem.style.width = 'max-content';
    const itemRects = elementItem.getClientRects();

    if (itemRects.length > 0 && itemRects[0].width > scrollWidth) {
        scrollWidth = itemRects[0].width;
    }

    elementItem.style.width = 'auto';
    return scrollWidth > elementItem.clientWidth;
}

文章:

https://bugs.chromium.org/p/chromium/issues/detail?id=980476

https://github.com/w3c/csswg-drafts/issues/4123

除了italo的答案,还可以使用jQuery来实现。

function isEllipsisActive($jQueryObject) {
    return ($jQueryObject.width() < $jQueryObject[0].scrollWidth);
}

另外,正如Smoky指出的那样,您可能希望使用jQuery outerWidth()而不是width()。

function isEllipsisActive($jQueryObject) {
    return ($jQueryObject.outerWidth() < $jQueryObject[0].scrollWidth);
}