前言
多行文本折叠在前端是一个很常见的交互, 如下图微博展示,当内容超过一定行数,会显示省略号 和"全文"按钮。那么该如何通过实现这样的效果呢?本文将介绍两种实现方案。
要实现这样的效果,主要分为两个部分:
- 1.当文案超过一定行数时截断内容并显示省略号
- 2.当内容超过行数时显示操作按钮
文案超过行数显示省略号
要实现文案超过行数显示省略号,只需要以下短短的几行代码即可实现:
xml
<style>
.text-container {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
<div class="text-container">
这里是一段可能比较长的文字,用来测试效果是否正确。
这里是一段可能比较长的文字,用来测试效果是否正确。
这里是一段可能比较长的文字,用来测试效果是否正确。
</div>
实现效果:
内容超过行数时显示操作按钮
上面通过 CSS 实现了超出内容的截断,但是是否显示"操作"按钮取决于当前内容是否存在截断。因此,需要先实现当前内容是否存在截断的判断。
当前内容是否存在截断
通过观察元素结构发现,如果当前内容存在截断,文案的实际内容高度比显示的文案内容高度高;否则就是没有发生内容截断。
根据上述判断,通过 js 实现当前内容是否存在截断的判断,代码如下:
ini
const textContainer = document.querySelector(".text-container");
const checkEllipsis = () => {
const range = document.createRange();
range.setStart(textContainer, 0);
range.setEnd(textContainer, textContainer.childNodes.length);
let rangeHeight = range.getBoundingClientRect().height;
let textContainerHeight = textContainer.getBoundingClientRect().height;
if (rangeHeight > textContainerHeight) {
console.log("当前内容存在截断");
} else {
console.log("当前内容没有截断");
}
}
此处用到了一个特殊的 API :createRange, 用于创建一个 Range 对象,表示文档中的一个范围。Range 对象通常用于选择文档中的一部分内容,然后对其进行操作。
操作按钮放置在下一行
接下来,就是放置操作按钮,正常应该把按钮放置在省略号右边,这样实现起来稍有难度,暂且放一放。先实现一个简单的效果,就是把按钮放置在下一行,具体实现代码如下:
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="description" content="baru belajar html" />
<title>Hello World!</title>
<style>
.text-container {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
}
.more-link {
display: none;
}
</style>
</head>
<body>
<div class="text-container">
这里是一段可能比较长的文字,用来测试效果是否正确。
这里是一段可能比较长的文字,用来测试效果是否正确。
<!-- 这里是一段可能比较长的文字,用来测试效果是否正确。 -->
</div>
<a href="#" class="more-link">详情</a>
<script>
const textContainer = document.querySelector(".text-container");
const moreLink = document.querySelector(".more-link");
const checkEllipsis = () => {
const range = document.createRange();
range.setStart(textContainer, 0);
range.setEnd(textContainer, textContainer.childNodes.length);
let rangeHeight = range.getBoundingClientRect().height;
let textContainerHeight = textContainer.getBoundingClientRect().height;
if (rangeHeight > textContainerHeight) {
console.log("当前内容存在截断");
moreLink.style.display = "inline-block";
} else {
console.log("当前内容没有截断");
moreLink.style.display = "none";
}
};
checkEllipsis();
</script>
</body>
</html>
实现效果:
按钮放置在省略号右边
实现思路:在文案元素中增加一个按钮元素,并设置按钮为浮动,这样文案就是环绕在按钮边上,然后设置按钮位置在右下角。在设置浮动元素定位的时候,要借助一个伪元素来布局,并清除浮动元素。
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="description" content="baru belajar html" />
<title>Hello World!</title>
<style>
.text-container {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.text-container::before {
content: "";
float: right;
width: 0px;
height: 100%;
margin-bottom: -28px;
/* background: red; */
}
.wrap {
display: flex;
}
.more-link {
display: none;
float: right;
clear: both;
}
</style>
</head>
<body>
<div class="wrap">
<div class="text-container">
<button class="more-link">展开</button>
浮动元素是如何定位的 正如我们前面提到的那样,当一个元素浮动之后,
它会被移出正常的文档流,然后向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。
</div>
</div>
<script>
const textContainer = document.querySelector(".text-container");
const moreLink = document.querySelector(".more-link");
if (textContainer.offsetHeight > textContainer.clientHeight) {
moreLink.style.display = "inline-block";
}
const checkEllipsis = () => {
const range = document.createRange();
range.setStart(textContainer, 0);
range.setEnd(textContainer, textContainer.childNodes.length);
let rangeHeight = range.getBoundingClientRect().height;
let textContainerHeight = textContainer.getBoundingClientRect().height;
if (rangeHeight > textContainerHeight) {
console.log("当前内容存在截断");
moreLink.style.display = "inline-block";
} else {
console.log("当前内容没有截断");
moreLink.style.display = "none";
}
};
checkEllipsis();
</script>
</body>
</html>
实现效果: