React中如何实现两行文本自动省略截断(适配可变宽度容器)
React 实现自适应宽度的两行文本省略截断
方案一:CSS原生实现(推荐,自适应容器宽度)
现代浏览器支持通过CSS属性直接实现多行省略,无需计算文本长度,完全适配容器的动态宽度。核心依赖-webkit-line-clamp属性,配合盒模型属性实现截断。
import React from 'react'; const TwoLineTruncatedText = ({ text }) => { return ( <div style={{ display: '-webkit-box', WebkitLineClamp: 2, // 指定显示行数 WebkitBoxOrient: 'vertical', overflow: 'hidden', textOverflow: 'ellipsis', // 可选:自定义内边距、行高 lineHeight: '1.5em', padding: '0 8px', }}> {text} </div> ); }; export default TwoLineTruncatedText;
兼容性:Chrome、Firefox 68+、Safari、Edge等现代浏览器均支持,无需额外逻辑,容器宽度变化时会自动调整截断范围。
方案二:JavaScript动态计算(兼容旧浏览器)
针对不支持-webkit-line-clamp的环境(如IE),可以通过动态计算文本高度实现自适应截断。核心思路是用隐藏容器模拟真实容器的布局,判断文本是否超出两行高度,再通过二分法高效截断文本。
import React, { useState, useEffect, useRef } from 'react'; const TwoLineTruncatedText = ({ text, baseFontSize = 16, lineHeight = 1.5 }) => { const [truncatedText, setTruncatedText] = useState(text); const displayRef = useRef(null); const hiddenRef = useRef(null); useEffect(() => { const truncateText = () => { if (!displayRef.current || !hiddenRef.current) return; // 同步隐藏容器与显示容器的宽度、行高 const containerWidth = displayRef.current.offsetWidth; hiddenRef.current.style.width = `${containerWidth}px`; hiddenRef.current.style.lineHeight = `${lineHeight}em`; hiddenRef.current.style.fontSize = `${baseFontSize}px`; hiddenRef.current.textContent = text; // 计算两行文本的最大允许高度 const maxHeight = baseFontSize * lineHeight * 2; if (hiddenRef.current.offsetHeight <= maxHeight) { setTruncatedText(text); return; } // 二分法查找可显示的最长文本长度 let left = 0; let right = text.length; let validLength = 0; while (left <= right) { const mid = Math.floor((left + right) / 2); const testText = text.slice(0, mid) + '...'; hiddenRef.current.textContent = testText; if (hiddenRef.current.offsetHeight <= maxHeight) { validLength = mid; left = mid + 1; } else { right = mid - 1; } } setTruncatedText(text.slice(0, validLength) + '...'); }; truncateText(); // 监听窗口 resize 或容器宽度变化,重新计算截断 window.addEventListener('resize', truncateText); return () => window.removeEventListener('resize', truncateText); }, [text, baseFontSize, lineHeight]); return ( <> <div ref={displayRef} style={{ lineHeight: `${lineHeight}em`, fontSize: `${baseFontSize}px`, overflow: 'hidden', padding: '0 8px', }} > {truncatedText} </div> {/* 用于计算的隐藏容器,不占用页面空间 */} <div ref={hiddenRef} style={{ position: 'absolute', visibility: 'hidden', whiteSpace: 'normal', left: '-9999px', top: 0, margin: 0, border: 'none', padding: 0, }} /> </> ); }; export default TwoLineTruncatedText;
注意事项:
- 需要根据实际场景调整
baseFontSize和lineHeight参数,确保高度计算准确 - 二分法比逐字符截断效率更高,适合长文本场景
- 若容器宽度受父组件布局影响而非窗口resize,可额外监听父容器的尺寸变化事件
内容的提问来源于stack exchange,提问作者Bian Artola
相关产品推荐
相关产品推荐

