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

Next.js项目实现文本溢出折叠展开(指定行数不截断)

Next.js实现指定行数文本折叠/展开功能

实现思路

核心是通过CSS实现指定行数的文本自然折叠,再结合React状态控制展开/收起,同时自定义“Read more”交互按钮,避免生硬截断文本内容。

可复用组件实现

创建TextCollapse.tsx客户端组件(需使用React状态):

'use client';

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

interface TextCollapseProps {
  text: string;
  maxLines: number;
  readMoreText?: string;
  readLessText?: string;
}

const TextCollapse = ({
  text,
  maxLines,
  readMoreText = 'Read more',
  readLessText = 'Read less',
}: TextCollapseProps) => {
  const [isExpanded, setIsExpanded] = useState(false);
  const textRef = useRef<HTMLDivElement>(null);
  const [needsTruncation, setNeedsTruncation] = useState(false);

  useEffect(() => {
    const checkIfTruncated = () => {
      if (!textRef.current) return;
      // 对比容器高度和内容滚动高度,判断是否需要折叠
      setNeedsTruncation(textRef.current.scrollHeight > textRef.current.clientHeight);
    };

    checkIfTruncated();
    // 监听窗口 resize,确保响应式场景下判断准确
    window.addEventListener('resize', checkIfTruncated);
    return () => window.removeEventListener('resize', checkIfTruncated);
  }, [text]);

  // 如果文本不需要折叠,直接显示全部内容
  if (!needsTruncation) {
    return <div>{text}</div>;
  }

  return (
    <div className="relative">
      <div
        ref={textRef}
        className={`transition-all duration-300 ${
          isExpanded ? 'line-clamp-none' : `line-clamp-${maxLines}`
        }`}
      >
        {text}
      </div>
      <button
        onClick={() => setIsExpanded(!isExpanded)}
        className="absolute bottom-0 right-0 bg-white px-2 text-blue-600 hover:text-blue-800 focus:outline-none"
      >
        {isExpanded ? readLessText : readMoreText}
      </button>
    </div>
  );
};

export default TextCollapse;

样式适配

若未使用Tailwind CSS,可自定义CSS实现line-clamp效果:

/* 通用截断基础样式 */
.line-clamp {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* 指定行数的截断类(示例为3行) */
.line-clamp-3 {
  -webkit-line-clamp: 3;
}

/* 展开时的样式 */
.line-clamp-none {
  display: block;
  -webkit-line-clamp: unset;
}

组件使用示例

在页面或其他组件中引入使用:

import TextCollapse from '@/components/TextCollapse';

export default function ArticlePage() {
  const articleContent = `这里是需要折叠的长文本内容,会被自动截断到指定行数,点击Read more按钮可以展开全部内容,点击Read less又会折叠回去。整个过程不会生硬截断文本,而是完整保留行内内容,完全符合你的需求。`;
  
  return (
    <div className="p-6 max-w-2xl mx-auto">
      <h2 className="text-xl font-bold mb-3">文章标题</h2>
      <TextCollapse text={articleContent} maxLines={3} />
    </div>
  );
}

核心要点

  • 通过scrollHeight与clientHeight的对比,精准判断文本是否需要折叠,避免按钮多余显示。
  • 利用CSS的-webkit-line-clamp实现指定行数的自然折叠,保证文本不会被生硬截断。
  • 用React状态控制展开/收起状态,配合过渡动画提升交互流畅度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:50:30