
本文介绍一种兼顾 googlebot 索引完整性与用户体验的纯前端文本折叠方案:使用 css `line-clamp` 控制行数,通过 js 切换 class 实现“显示更多/更少”,确保搜索引擎可完整抓取原始内容。
在 Nuxt 3 项目中实现“三行截断 + 展开按钮”功能时,关键目标是:对用户友好(视觉上折叠)、对 SEO 友好(HTML 中保留全部文本,不依赖 v-if 或动态渲染隐藏内容)。这意味着不能用 v-show="false"、v-if="showAll" 或 display: none 隐藏文字——这些方式可能导致 Googlebot 无法索引被隐藏的内容。
✅ 正确做法是:所有文本始终存在于 DOM 中,仅通过 CSS 视觉截断;点击按钮仅切换 line-clamp 值,不增删节点、不修改 innerHTML。
✅ 推荐实现方案(Nuxt 3 兼容)
1. HTML 结构(服务端渲染友好)
<!-- 在 .vue 组件模板中直接写入 --> <p class="lines-3"> Lorem ipsum dolor sit amet, consectetur adipiscing elit... </p> <button class="show-more"></button>
⚠️ 注意:<p> 和 <button> 必须相邻(button 是 p 的紧邻兄弟节点),以便 JS 通过 previousElementSibling 准确定位。
2. CSS 样式(支持 WebKit + 回退兼容)
/* 支持 line-clamp 的基础样式 */
[class^="lines-"] {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
/* 关键:启用行数限制 */
-webkit-line-clamp: 3; /* 默认值,可被覆盖 */
}
.lines-1 { -webkit-line-clamp: 1; }
.lines-2 { -webkit-line-clamp: 2; }
.lines-3 { -webkit-line-clamp: 3; }
/* 展开状态:取消行数限制 */
.lines-all {
-webkit-line-clamp: unset;
/* 可选:重置高度以避免残留溢出 */
max-height: none;
}
/* 按钮文字动态切换 */
.show-more {
border: none;
background: none;
padding: 0;
font: inherit;
cursor: pointer;
color: #007bff;
text-decoration: underline;
}
.show-more::after {
content: 'Show More';
}
.show-more[data-show-all="true"]::after {
content: 'Show Less';
}3. JavaScript 行为(建议放在 onMounted 中)
// 在 setup() 或 <script setup> 中
import { onMounted } from 'vue'
onMounted(() => {
const handleClick = (e: MouseEvent) => {
if (!(e.target instanceof HTMLElement)) return
if (!e.target.classList.contains('show-more')) return
const btn = e.target
const content = btn.previousElementSibling as HTMLElement | null
if (!content || !content.classList) return
const showAll = btn.dataset.showAll === 'true'
content.classList.toggle('lines-all', !showAll)
btn.dataset.showAll = String(!showAll)
}
document.addEventListener('click', handleClick)
return () => document.removeEventListener('click', handleClick)
})✅ Nuxt 3 提示:将事件监听器绑定到 document 是安全的(服务端无 DOM),且 onMounted 确保只在客户端执行;同时记得清理监听器防止内存泄漏。
4. 进阶优化建议
-
无障碍支持(a11y):为按钮添加 aria-expanded 和 aria-controls:
<button class="show-more" :aria-expanded="showAll.toString()" :aria-controls="'desc-' + id"> </button> <p :id="'desc-' + id" class="lines-3">...</p> - 过渡动画:line-clamp 本身不支持 CSS 动画,但可通过 max-height + transition 模拟(需预估最大高度,适用性有限)。
- SSR 安全性:本方案所有文本均在初始 HTML 中输出,Googlebot 可 100% 抓取完整内容,完全符合 SEO 最佳实践。
✅ 总结
该方案零依赖、轻量、SEO 安全,完美适配 Nuxt 3 的 SSR/SSG 构建流程。核心原则是:内容永远可见(DOM 中存在),仅视觉折叠;交互仅改变 CSS 属性,不遮蔽、不销毁、不延迟加载。开发者可放心复用至产品描述、博客摘要、FAQ 等多类长文本场景。










