我在页面上有一个块元素的集合。它们都有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的文本内容。


当前回答

添加到@Дмытрык的答案,缺失的边界和填充的演绎是完全有效的!!

const items = Array.from(document.querySelectorAll('.item')); items.forEach(item =>{ item.style.color = checkEllipsis(item) ? 'red': 'black' }) function checkEllipsis(el){ const styles = getComputedStyle(el); const widthEl = parseFloat(styles.width); const ctx = document.createElement('canvas').getContext('2d'); ctx.font = `${styles.fontSize} ${styles.fontFamily}`; const text = ctx.measureText(el.innerText); let extra = 0; extra += parseFloat(styles.getPropertyValue('border-left-width')); extra += parseFloat(styles.getPropertyValue('border-right-width')); extra += parseFloat(styles.getPropertyValue('padding-left')); extra += parseFloat(styles.getPropertyValue('padding-right')); return text.width > (widthEl - extra); } .item{ width: 60px; overflow: hidden; text-overflow: ellipsis; } <div class="item">Short</div> <div class="item">Loooooooooooong</div>

其他回答

添加到@Дмытрык的答案,缺失的边界和填充的演绎是完全有效的!!

const items = Array.from(document.querySelectorAll('.item')); items.forEach(item =>{ item.style.color = checkEllipsis(item) ? 'red': 'black' }) function checkEllipsis(el){ const styles = getComputedStyle(el); const widthEl = parseFloat(styles.width); const ctx = document.createElement('canvas').getContext('2d'); ctx.font = `${styles.fontSize} ${styles.fontFamily}`; const text = ctx.measureText(el.innerText); let extra = 0; extra += parseFloat(styles.getPropertyValue('border-left-width')); extra += parseFloat(styles.getPropertyValue('border-right-width')); extra += parseFloat(styles.getPropertyValue('padding-left')); extra += parseFloat(styles.getPropertyValue('padding-right')); return text.width > (widthEl - extra); } .item{ width: 60px; overflow: hidden; text-overflow: ellipsis; } <div class="item">Short</div> <div class="item">Loooooooooooong</div>

我认为更好的检测方法是使用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是这样工作的

你可以这样检测

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

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

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

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

如果你有反应,我是这么做的。

<div 
  ref={ref => {
    if (!ref) return
    const isOverflowing = ref.scrollWidth > ref.clientWidth
    if (isOverflowing) {
      // handle what to do next here
    }
  }}
/>

所有的解决方案并没有真正为我工作,什么工作是比较元素scrollWidth其父(或子,取决于哪个元素有触发器)的scrollWidth。

当子进程的scrollWidth大于父进程的scrollWidth时,就意味着.text-省略号是活动的。


当el是父元素时

function isEllipsisActive(el) {
    let width       = el.offsetWidth;
    let widthChild  = el.firstChild.offsetWidth;
    return (widthChild >= width);
}

当el是子元素时

function isEllipsisActive(event) {
    let width       = el.offsetWidth;
    let widthParent = el.parentElement.scrollWidth;
    return (width >= widthParent);
}