本文介绍在 next.js 项目中优雅实现多行文本自动截断(按行数而非字符数),点击“read more”展开全文,并支持收起,兼顾可访问性与视觉一致性。
本文介绍在 next.js 项目中优雅实现多行文本自动截断(按行数而非字符数),点击“read more”展开全文,并支持收起,兼顾可访问性与视觉一致性。
在实际开发中,卡片类组件常需展示摘要文本(如新闻、产品描述),但受限于布局空间,必须控制显示行数——关键需求是“按指定行数截断”,而非简单限制字符或字数。CSS 原生不支持 line-clamp 在所有场景下可靠工作(尤其配合 Flex/Grid 或动态字体时),因此推荐结合 CSS max-height + JS 状态控制的稳健方案。
以下是一个生产就绪的 CollapsibleText 组件示例(适用于 Next.js App Router):
// components/CollapsibleText.tsx
'use client';
import { useState, useEffect } from 'react';
interface CollapsibleTextProps {
children: string;
lines?: number; // 控制默认显示行数(默认 3 行)
className?: string;
}
export default function CollapsibleText({
children,
lines = 3,
className = ''
}: CollapsibleTextProps) {
const [expanded, setExpanded] = useState(false);
const [isClamped, setIsClamped] = useState(true);
// 动态计算每行高度并设置 max-height(兼容不同字体/字号)
useEffect(() => {
const el = document.querySelector<HTMLElement>('.collapsible-text');
if (!el) return;
const lineHeight = parseFloat(getComputedStyle(el).lineHeight) || 1.5;
const fontSize = parseFloat(getComputedStyle(el).fontSize) || 16;
const baseHeight = lineHeight * fontSize;
const maxHeight = expanded ? 'none' : `${baseHeight * lines}px`;
el.style.maxHeight = maxHeight;
setIsClamped(!expanded && el.scrollHeight > el.clientHeight);
}, [expanded, lines]);
return (
<div className="flex flex-col">
<p
className={`collapsible-text transition-all duration-300 ease-in-out ${className}`}
style={{ overflow: 'hidden' }}
>
{children}
</p>
{isClamped && (
<button
type="button"
onClick={() => setExpanded(!expanded)}
className="mt-2 text-blue-600 hover:underline text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-300 rounded"
aria-expanded={expanded}
aria-controls="collapsible-content"
>
{expanded ? 'Read less' : 'Read more'}
</button>
)}
</div>
);
}✅ 使用方式:
// 在页面中
import CollapsibleText from '@/components/CollapsibleText';
export default function HomePage() {
return (
<article className="max-w-2xl mx-auto p-4">
<CollapsibleText lines={2}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...
</CollapsibleText>
</article>
);
}⚠️ 注意事项:
- 必须添加 'use client' 指令,因组件依赖 useState 和 useEffect;
- lineHeight 计算基于真实渲染样式,比硬编码 50px 更鲁棒(适配响应式字体);
- 使用 <button> 替代 <p> 实现“Read more”,确保键盘可访问性(Enter/Space 触发)和语义正确性;
- aria-expanded 和 aria-controls 提升屏幕阅读器体验;
- 若需服务端渲染(SSR)友好,可配合 useLayoutEffect 或首屏预判 isClamped 状态。
该方案不依赖第三方库,零运行时开销,完美契合 Next.js 的现代 React 生态,同时满足设计稿中“严格控行”与交互反馈的双重需求。


















