实现文本两行溢出展开收起效果的完整方案
在前端页面开发中,经常会遇到长文本展示的场景,为了提升页面布局的整洁性,通常会将超出指定行数的文本隐藏,并提供展开/收起的交互按钮。本文将详细介绍如何通过CSS和JavaScript配合,实现文本溢出两行时的展开收起效果。
一、实现原理概述
整个功能的实现分为两个核心部分:
CSS部分:通过
-webkit-line-clamp属性限制文本显示的行数,配合溢出隐藏样式实现初始的两行截断效果。JavaScript部分:判断文本实际高度是否超过两行对应的高度,决定是否显示展开按钮;同时监听按钮点击事件,切换文本的显示状态。
二、基础HTML结构
首先我们需要准备基础的DOM结构,包含文本容器和展开/收起按钮:
<div class="text-container" id="textContainer"> 这是一段很长的测试文本,用于演示文本溢出两行的展开收起效果。当文本内容超出两行时,会自动隐藏多余部分,并显示展开按钮;点击展开按钮可以查看全部内容,点击收起按钮可以恢复截断状态。这是一段很长的测试文本,用于演示文本溢出两行的展开收起效果。 </div> <div class="toggle-btn" id="toggleBtn" style="display: none;">展开</div>
三、CSS样式实现
接下来编写对应的CSS样式,核心是实现两行文本截断的效果,同时定义展开/收起按钮的基础样式:
/* 两行文本截断样式 */
.text-container {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2; /* 限制显示2行 */
overflow: hidden;
text-overflow: ellipsis;
line-height: 24px; /* 行高,可根据实际需求调整 */
max-height: 48px; /* 2行 * 行高,用于JS判断高度 */
font-size: 14px;
color: #333;
margin-bottom: 8px;
}
/* 展开/收起按钮样式 */
.toggle-btn {
color: #1890ff;
cursor: pointer;
font-size: 14px;
user-select: none;
}
/* 展开状态下的文本容器样式 */
.text-container.expanded {
-webkit-line-clamp: unset;
max-height: none;
overflow: visible;
}这里需要注意,-webkit-line-clamp是WebKit内核浏览器的私有属性,目前主流现代浏览器都已经支持该属性,如果需要兼容更老的浏览器,可以结合max-height和overflow:hidden做降级处理,不过本文方案适用于绝大多数现代项目场景。
四、JavaScript逻辑实现
JavaScript部分需要完成两个核心功能:判断文本是否溢出两行、处理展开/收起的切换逻辑。
1. 判断文本是否溢出两行
我们可以通过对比文本容器的scrollHeight和clientHeight来判断文本是否溢出:如果scrollHeight大于clientHeight,说明文本的实际高度超过了容器显示的高度,也就是发生了溢出。
// 获取DOM元素
const textContainer = document.getElementById('textContainer');
const toggleBtn = document.getElementById('toggleBtn');
// 判断文本是否溢出两行
function isTextOverflow() {
// 临时移除展开状态,获取原始截断状态下的高度
const isExpanded = textContainer.classList.contains('expanded');
if (isExpanded) {
textContainer.classList.remove('expanded');
}
// scrollHeight是内容实际高度,clientHeight是容器可见高度
const isOverflow = textContainer.scrollHeight > textContainer.clientHeight;
// 恢复原来的展开状态
if (isExpanded) {
textContainer.classList.add('expanded');
}
return isOverflow;
}2. 初始化状态与切换逻辑
页面加载完成后,先判断文本是否溢出,如果溢出则显示展开按钮;然后给按钮绑定点击事件,切换展开/收起状态。
// 初始化函数
function initToggle() {
// 判断是否需要显示展开按钮
if (isTextOverflow()) {
toggleBtn.style.display = 'block';
toggleBtn.textContent = '展开';
} else {
toggleBtn.style.display = 'none';
}
}
// 切换展开/收起状态
function toggleText() {
const isExpanded = textContainer.classList.contains('expanded');
if (isExpanded) {
// 当前是展开状态,切换为收起
textContainer.classList.remove('expanded');
toggleBtn.textContent = '展开';
} else {
// 当前是收起状态,切换为展开
textContainer.classList.add('expanded');
toggleBtn.textContent = '收起';
}
}
// 页面加载完成后初始化
window.addEventListener('DOMContentLoaded', () => {
initToggle();
// 绑定按钮点击事件
toggleBtn.addEventListener('click', toggleText);
});五、完整示例整合
将上面的HTML、CSS、JavaScript整合到一起,就可以得到完整的可运行示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文本两行溢出展开收起示例</title>
<style>
.text-container {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
line-height: 24px;
max-height: 48px;
font-size: 14px;
color: #333;
margin-bottom: 8px;
width: 300px; /* 为了演示效果,限制容器宽度 */
}
.text-container.expanded {
-webkit-line-clamp: unset;
max-height: none;
overflow: visible;
}
.toggle-btn {
color: #1890ff;
cursor: pointer;
font-size: 14px;
user-select: none;
display: none;
}
</style>
</head>
<body>
<div class="text-container" id="textContainer">
这是一段很长的测试文本,用于演示文本溢出两行的展开收起效果。当文本内容超出两行时,会自动隐藏多余部分,并显示展开按钮;点击展开按钮可以查看全部内容,点击收起按钮可以恢复截断状态。这是一段很长的测试文本,用于演示文本溢出两行的展开收起效果。
<>
<div class="toggle-btn" id="toggleBtn">展开</div>
<script>
const textContainer = document.getElementById('textContainer');
const toggleBtn = document.getElementById('toggleBtn');
function isTextOverflow() {
const isExpanded = textContainer.classList.contains('expanded');
if (isExpanded) {
textContainer.classList.remove('expanded');
}
const isOverflow = textContainer.scrollHeight > textContainer.clientHeight;
if (isExpanded) {
textContainer.classList.add('expanded');
}
return isOverflow;
}
function initToggle() {
if (isTextOverflow()) {
toggleBtn.style.display = 'block';
toggleBtn.textContent = '展开';
} else {
toggleBtn.style.display = 'none';
}
}
function toggleText() {
const isExpanded = textContainer.classList.contains('expanded');
if (isExpanded) {
textContainer.classList.remove('expanded');
toggleBtn.textContent = '展开';
} else {
textContainer.classList.add('expanded');
toggleBtn.textContent = '收起';
}
}
window.addEventListener('DOMContentLoaded', () => {
initToggle();
toggleBtn.addEventListener('click', toggleText);
});
</script>
</body>
</html>六、注意事项
如果文本内容会动态变化,需要在内容更新后重新调用
initToggle方法,重新判断是否需要显示展开按钮。行高和
max-height需要保持对应,避免出现判断误差,比如行高是24px,两行就是48px,max-height就设置为48px。如果需要兼容非WebKit内核的浏览器,可以替换
-webkit-line-clamp的实现方式,比如使用max-height配合overflow:hidden,结合伪元素添加省略号,但这种方式不如-webkit-line-clamp灵活。
以上就是实现文本两行溢出展开收起效果的完整方案,该方案逻辑清晰、兼容性好,可直接应用到实际项目中。