
本文介绍在 next.js 项目中优雅实现多行文本自动截断(按行数而非字符数)并支持点击“阅读更多”展开全文的完整方案,包含 react 状态控制、css 高度过渡动画及响应式注意事项。
本文介绍在 next.js 项目中优雅实现多行文本自动截断(按行数而非字符数)并支持点击“阅读更多”展开全文的完整方案,包含 react 状态控制、css 高度过渡动画及响应式注意事项。
在 Next.js(或任意 React)应用中,仅靠 text-overflow: ellipsis 无法实现按指定行数折叠多行文本(如“最多显示3行,超出部分隐藏+Read more”),因为 CSS 的 line-clamp 虽可实现行数限制,但缺乏平滑展开交互。更可靠的方式是结合 max-height 控制 + transition 动画 + React 状态管理,确保视觉连贯且语义清晰。
以下是一个生产就绪的 CollapsibleText 组件示例:
// components/CollapsibleText.tsx
'use client';
import { useState, useEffect } from 'react';
interface CollapsibleTextProps {
children: string;
lines?: number; // 默认显示行数,如 2 或 3
readMoreText?: string;
readLessText?: string;
}
export default function CollapsibleText({
children,
lines = 2,
readMoreText = '阅读更多',
readLessText = '收起',
}: CollapsibleTextProps) {
const [expanded, setExpanded] = useState(false);
const [isClient, setIsClient] = useState(false);
// 确保仅在客户端计算行高(服务端无 window)
useEffect(() => {
setIsClient(true);
}, []);
// 动态计算基础行高(假设 1.5 行高,font-size 16px → 每行约 24px)
const lineHeight = 24; // 可根据实际字体调整
const collapsedHeight = lines * lineHeight;
return (
<div className="collapsible-container">
<div
className={`collapsible-text ${expanded ? 'expanded' : 'collapsed'}`}
style={{
maxHeight: expanded ? 'none' : `${collapsedHeight}px`,
transition: 'max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
}}
>
{children}
</div>
<button
type="button"
className="read-toggle"
onClick={() => setExpanded(!expanded)}
aria-expanded={expanded}
aria-controls="collapsible-content"
>
{expanded ? readLessText : readMoreText}
</button>
</div>
);
}配套 CSS(建议使用 CSS Modules 或全局样式):
/* styles/CollapsibleText.module.css */
.collapsible-container {
margin-bottom: 1rem;
}
.collapsible-text {
overflow: hidden;
line-height: 1.5;
/* 关键:禁用换行截断干扰,确保自然折行 */
word-break: break-word;
hyphens: auto;
}
.read-toggle {
background: none;
border: none;
color: #007bff;
font-size: 0.875rem;
cursor: pointer;
padding: 0;
text-align: left;
margin-top: 0.5rem;
}
.read-toggle:hover {
text-decoration: underline;
}
/* 可选:添加展开/收起图标 */
.read-toggle::after {
content: ' ▼';
font-size: 0.7em;
margin-left: 4px;
}
.read-toggle.expanded::after {
content: ' ▲';
}? 关键注意事项:
- ✅ 避免硬编码 max-height:本例通过 lines * lineHeight 动态计算,适配不同字体大小;若需更高精度,可用 useRef + getBoundingClientRect().height 测量首屏渲染后高度(适用于复杂排版)。
- ✅ 服务端渲染(SSR)兼容:使用 useEffect 延迟 isClient 判断,防止 hydration mismatch;初始状态设为 false,确保首屏默认折叠。
- ✅ 无障碍友好:添加 aria-expanded 和 aria-controls,屏幕阅读器可感知状态变化。
- ⚠️ 动画局限性:max-height: none 无法参与 CSS 过渡,因此动画仅在折叠时生效;如需双向平滑,可改用 height + scrollHeight 动态计算(需 useRef 获取 DOM 节点)。
- ? 响应式增强:可通过 useMediaQuery 在小屏下调低 lines 值(如移动端默认 1 行)。
最后,在页面中使用:
import CollapsibleText from '@/components/CollapsibleText';
export default function HomePage() {
return (
<article className="prose max-w-none">
<CollapsibleText lines={3}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...
</CollapsibleText>
</article>
);
}该方案兼顾语义化、可访问性与视觉体验,无需第三方库,轻量且易于定制,是 Next.js 多行文本折叠场景的推荐实践。


















