如何移除CSS ellipsis截断后HTML元素内的剩余文本?
问题
通过CSS规则text-overflow: ellipsis;和overflow: hidden;实现文本截断时,当文本过长换行,偶尔会显示下一行的部分像素。而且element.innerHTML无法获取到ellipsis的省略号,没法用正则检测并移除这部分残留文本。请问如何移除HTML元素中ellipsis截断后的剩余文本?要求示例中的div高度保持不变。
示例代码
HTML
<div id='header-inner'></div>
CSS
#header-inner { height: 80px; display: -webkit-box; font-size: 15px; font-weight: normal; font-style: normal; text-decoration: none; border-width: 1px; max-height: 62px; text-overflow: ellipsis; overflow: hidden; -moz-box-orient: vertical; white-space: unset; -webkit-line-clamp: 3; padding-top: 0px; }
JavaScript
let ele = document.getElementById('header-inner'); ele.innerHTML = 'There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which ';
解决方案
方法一:用测试元素计算可容纳文本长度
既然你用了-webkit-line-clamp: 3限制最多3行,我们可以创建一个和目标元素样式完全一致的隐藏测试元素,逐步添加文本直到高度超出限制,以此确定可容纳的最大文本长度,再手动截断加省略号。这种方法兼容性好,适合大多数场景。
document.addEventListener('DOMContentLoaded', () => { const targetEle = document.getElementById('header-inner'); const testEle = document.createElement('div'); // 复制目标元素的所有样式 testEle.style.cssText = getComputedStyle(targetEle).cssText; // 隐藏测试元素,不影响页面布局 testEle.style.position = 'absolute'; testEle.style.visibility = 'hidden'; testEle.style.overflow = 'visible'; testEle.style.maxHeight = 'none'; document.body.appendChild(testEle); const originalText = targetEle.textContent.trim(); let truncatedText = ''; const maxHeight = parseInt(getComputedStyle(targetEle).maxHeight); for (let i = 0; i < originalText.length; i++) { testEle.textContent = originalText.slice(0, i + 1); if (testEle.offsetHeight > maxHeight) { // 截断到前一个字符,加上省略号 truncatedText = originalText.slice(0, i) + '...'; break; } } // 如果文本本来就没超过限制,直接用原文本 if (!truncatedText) truncatedText = originalText; targetEle.textContent = truncatedText; // 移除测试元素 document.body.removeChild(testEle); });
方法二:利用Range API截取可见文本
Range API可以精准获取元素内的可见文本范围,我们可以通过它找到可视区域内的文本,再处理截断(避免截断到单词中间)。
document.addEventListener('DOMContentLoaded', () => { const targetEle = document.getElementById('header-inner'); const range = document.createRange(); const originalText = targetEle.textContent.trim(); // 选中目标元素内的所有内容 range.selectNodeContents(targetEle); const rect = targetEle.getBoundingClientRect(); // 调整Range,只保留可视区域内的部分 let endOffset = range.endOffset; while (range.getBoundingClientRect().bottom > rect.bottom) { endOffset--; range.setEnd(targetEle.firstChild, endOffset); } let visibleText = range.toString().trim(); // 找到最后一个空格,避免截断单词 const lastSpaceIdx = visibleText.lastIndexOf(' '); if (lastSpaceIdx > 0) { visibleText = visibleText.slice(0, lastSpaceIdx) + '...'; } else if (visibleText.length < originalText.length) { visibleText += '...'; } targetEle.textContent = visibleText; });
注意点
- 两种方法都要等元素样式渲染完成后再执行,比如放在
DOMContentLoaded回调里 - 原div的高度会保持不变,只修改文本内容
- 方法一受字体、字间距等样式影响小,方法二适合复杂排版场景
内容的提问来源于stack exchange,提问作者Gustė
相关产品推荐
相关产品推荐

