如何使用Range API实现容器内文本的自动截断?
嘿,这个需求我之前折腾过,用原生的Range API完全能搞定,不用依赖任何jQuery插件,我给你捋清楚具体的实现思路和代码:
核心思路
你的容器是固定高度,里面有多个独立的文本块,我们要做的就是:
- 逐个检查每个文本块的高度,累计起来判断什么时候会超出容器高度
- 找到第一个会导致溢出的文本块,用Range API逐步截断它的内容,直到加上前面的累计高度刚好不超过容器高度
- 截断后加上省略号,同时隐藏后面所有的文本块
具体代码实现
HTML(修正了你原来未闭合的标签)
<div class="container"> <div class="text">Lorem lorem lorem lorem lorem</div> <div class="text">Lorem lorem lorem lorem lorem</div> <div class="text">Lorem lorem lorem lorem lorem</div> </div>
CSS
.container { height: 60px; border: 1px solid black; overflow: hidden; /* 防止截断后的内容意外溢出 */ } .text { line-height: 20px; /* 可选,设置行高方便计算行数,让截断更精准 */ margin: 4px 0; /* 可选,根据你的排版需求调整 */ }
JavaScript(用Range API实现截断)
function truncateContainerContent(containerSelector) { const container = document.querySelector(containerSelector); if (!container) return; // 存储每个文本块的原始内容,方便后续resize时恢复 const textElements = Array.from(container.querySelectorAll('.text')); textElements.forEach(el => { if (!el.dataset.originalText) { el.dataset.originalText = el.textContent; } }); const containerAvailableHeight = container.clientHeight; let totalUsedHeight = 0; let truncateTargetIndex = -1; // 第一步:找到第一个会导致容器溢出的文本块 for (let i = 0; i < textElements.length; i++) { const el = textElements[i]; // 先恢复原始文本,保证高度计算准确 el.textContent = el.dataset.originalText; el.style.display = ''; const elHeight = el.offsetHeight; if (totalUsedHeight + elHeight > containerAvailableHeight) { truncateTargetIndex = i; break; } totalUsedHeight += elHeight; } // 如果所有文本块都能放下,直接结束 if (truncateTargetIndex === -1) return; // 第二步:用Range API截断目标文本块 const targetEl = textElements[truncateTargetIndex]; const remainingHeight = containerAvailableHeight - totalUsedHeight; const range = document.createRange(); // 选中目标元素的所有内容 range.selectNodeContents(targetEl); // 从文本末尾开始逐步截断,直到元素高度符合剩余空间要求 while (targetEl.offsetHeight > remainingHeight && range.toString().length > 0) { // 将Range的结束位置向前移动一个字符 range.setEnd(range.endContainer, range.endOffset - 1); // 更新元素文本,加上省略号 targetEl.textContent = range.toString() + '...'; } // 极端情况:如果连省略号都放不下,直接隐藏这个文本块 if (targetEl.offsetHeight > remainingHeight) { targetEl.style.display = 'none'; truncateTargetIndex++; } // 第三步:隐藏后面所有的文本块 for (let i = truncateTargetIndex + 1; i < textElements.length; i++) { textElements[i].style.display = 'none'; } } // 初始化调用,处理容器 truncateContainerContent('.container'); // 可选:窗口大小变化时重新截断(比如容器高度随窗口变化的场景) window.addEventListener('resize', () => { truncateContainerContent('.container'); });
关键细节说明
- Range API的作用:通过
createRange()创建范围对象,selectNodeContents选中元素内的所有文本,然后用setEnd逐步收缩范围,实现精准的字符级截断,比单纯截取字符串更可靠(比如处理多行文本时,能准确识别换行) - 兼容性:Range API在IE9及以上的浏览器都支持,完全覆盖现代浏览器
- 可扩展性:如果你的容器高度是动态变化的,只需要在高度变化时重新调用
truncateContainerContent函数即可,代码里已经包含了resize的处理逻辑
内容的提问来源于stack exchange,提问作者Rami Chasygov
相关产品推荐
相关产品推荐

