需求就是超过四行得有个展开按钮,点击展开显示所有内容,不超过四行的话就不需要这个按钮并显示所有内容。且按钮在段落的后面
- 首先得判断文本自否超过四行,因为这些一般都是是前端异步请求然后后端发送过来,使用了 Vue 中的 nextTick 来监听 DOM 中是数据变化。
- 接下来主要是 css 上的思路,其实可以分为两部分,如下图,标号1的部分展示前面三行,标号为2的部分会根据1的行数判断缩进的大小,然后展示第四行。最后通过背景色的控制让两者看上去是一段文字。
主要的点:
第一部分:定位在文本框左上角,是三行高度直接截断
第二部分:定位在文本框左上角,是4行高度写上省略号样式,右边空出五个字距离,然后整体缩进15个字,这样上面三行前面实际和第一部分重合,加上背景色与层级,会看的像一段文字
{
padding-right: 5em;
text-intent: 15em;
}
第三部分:定位在右下角的展开全文的汉字,根据文本框里文本的真实高度是否大于4行来决定是否展示
<template>
<div
class="text-box"
:class="isCusp ? 'text-cusp-box' : ''"
>
<div
class="text-desc"
:class="isOpen ? 'total-desc' : ''"
:title="title ? title+':'+content : content"
>
<div class="text-con" ref="desc">
<span
class="text-title"
v-if="title"
>{{title}}:</span>{{content}}
</div>
<div
class="text-opt"
v-if="isBtn"
@click="change"
>{{isOpen ? '收起全文' : '展开全文'}}</div>
</div>
</div>
</template>
<script>
export default {
props: {
// 文字标题
title: {
type: String,
default: ''
},
// 文字内容
content: {
type: String,
default: ''
},
// 是否有尖头指向
isCusp: {
type: Boolean,
default: false
}
},
data() {
return {
// 内容信息
info: '',
// 是否展示按钮
isBtn: false,
// 按钮样子
isOpen: true
};
},
methods: {
change() {
this.isOpen = !this.isOpen;
}
},
mounted() {
this.info = this.content;
},
watch: {
info(val) {
let descHeight = window
.getComputedStyle(this.$refs.desc)
.height.replace('px', '');
let rem = window.getComputedStyle(this.$refs.desc).lineHeight.replace('px', '');
// 超过了四行
if (descHeight > rem * 4) {
// 显示展开收起按钮
this.isBtn = true;
this.isOpen = false;
} else {
// 不显示展开收起按钮
this.isBtn = false;
this.isOpen = true;
}
}
}
};
</script>
<style lang="less" scoped>
.text-box {
background: #f3f6f9;
padding: 16px;
border-radius: 8px;
.text-desc {
position: relative;
max-height: 144px;
line-height: 36px;
word-wrap: break-word;
word-break: break-all;
overflow: hidden;
.text-con {
font-size: 24px;
color: #77808a;
line-height: 36px;
.text-title {
font-weight: bold;
}
}
// 这是展开前实际显示的内容
&:after,
&:before {
content: attr(title);
position: absolute;
left: 0;
top: 0;
width: 100%;
font-size: 24px;
color: #77808a;
line-height: 36px;
background: #f3f6f9;
}
// 把最后最后一行自身的上面三行遮住
&:before {
display: block;
overflow: hidden;
z-index: 1;
max-height: 108px;
}
&:after {
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
height: 144px;
-webkit-line-clamp: 4;
text-overflow: ellipsis;
-webkit-box-sizing: border-box;
box-sizing: border-box;
text-indent: -15em;
padding-right: 5em;
}
&.total-desc{
max-height: none;
}
&.total-desc:before{display: none;}
&.total-desc:after{display: none;}
}
&.text-cusp-box {
position: relative;
margin-top: 30px;
&:before {
content: '';
height: 0px;
width: 0px;
position: absolute;
top: -14px;
left: 105px;
margin-left: -10px;
z-index: 1;
border-left: 14px solid transparent;
border-right: 14px solid transparent;
border-bottom: 24px solid #f3f6f9;
}
}
.text-opt {
position: absolute;
font-size: 24px;
color: #00c0eb;
line-height: 36px;
bottom: 0px;
right: 0;
z-index: 10;
}
}
</style>