You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中基于视口宽度将文本拆分为无换行单行

React实现文本按视口宽度拆分单行块

核心思路

要实现文本根据视口宽度动态拆分为单行块,关键在于实时测量文本宽度,并根据容器(或视口)宽度判断哪些单词可以放在同一行。具体步骤如下:

  • 将原始文本拆分为单词数组
  • 使用隐藏容器测量文本片段的宽度
  • 逐步将单词加入当前行,直到加入下一个单词会超出容器宽度,此时将当前行存入结果数组并开始新行
  • 监听窗口 resize 事件,在视口变化时重新计算行结构
  • 渲染每个行块并设置样式保证单行显示

实现代码

CSS 样式

/* 单行文本块样式,确保不换行 */
.line {
  white-space: nowrap;
  margin-bottom: 8px; /* 可选:行间距 */
}

/* 隐藏的测量容器,用于计算文本宽度 */
.measure-container {
  position: absolute;
  visibility: hidden;
  white-space: nowrap;
  /* 必须与 .line 类的字体样式一致,保证测量准确 */
  font-size: 16px;
  font-family: sans-serif;
}

React 组件

import { useState, useRef, useEffect } from 'react';

const TextSplitter = ({ text }) => {
  const [lines, setLines] = useState([]);
  const wordsRef = useRef(text.split(' ')); // 存储拆分后的单词数组
  const measureRef = useRef(null); // 测量容器的引用
  const containerRef = useRef(null); // 显示容器的引用

  // 计算行结构的核心函数
  const calculateLines = () => {
    if (!measureRef.current || !containerRef.current) return;
    
    const containerWidth = containerRef.current.offsetWidth;
    const currentLine = [];
    const newLines = [];
    
    wordsRef.current.forEach(word => {
      // 临时将单词加入当前行,测量宽度
      currentLine.push(word);
      const lineText = currentLine.join(' ');
      measureRef.current.textContent = lineText;
      const lineWidth = measureRef.current.offsetWidth;
      
      // 如果当前行宽度超过容器,移除刚加入的单词,将当前行存入结果
      if (lineWidth > containerWidth) {
        currentLine.pop();
        if (currentLine.length > 0) {
          newLines.push(currentLine.join(' '));
          currentLine.length = 0;
        }
        // 将当前单词放入新行
        currentLine.push(word);
      }
    });
    
    // 处理最后一行剩余的单词
    if (currentLine.length > 0) {
      newLines.push(currentLine.join(' '));
    }
    
    setLines(newLines);
  };

  // 初始化计算 + 监听窗口 resize
  useEffect(() => {
    calculateLines();
    window.addEventListener('resize', calculateLines);
    return () => window.removeEventListener('resize', calculateLines);
  }, [text]);

  return (
    <div ref={containerRef}>
      {/* 隐藏的测量容器 */}
      <div ref={measureRef} className="measure-container"></div>
      {/* 渲染所有单行块 */}
      {lines.map((line, index) => (
        <div key={index} className="line">{line}</div>
      ))}
    </div>
  );
};

// 组件使用示例
const App = () => {
  const text = 'Lorem ipsum dolor sit amet consectetur adipisicing elit Eos blanditiis quia minima dignissimos nostrum accusantium iure quam recusandae modi reiciendis';
  return <TextSplitter text={text} />;
};

export default App;

关键说明

  • 测量准确性: 隐藏容器的字体样式必须与实际行块一致,否则测量的宽度会有偏差
  • 响应式适配: 通过监听 resize 事件,在视口宽度变化时自动重新计算行结构
  • 单行保证: .line 类的 white-space: nowrap 属性确保每个文本块始终保持单行,不会自动换行
  • 容器宽度: 行的宽度由 containerRef 指向的容器决定,如果需要适配整个视口,只需让该容器占满视口宽度即可

内容的提问来源于stack exchange,提问作者saimarshadd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:06:04