js文本多行实现展开、收起效果

2,829 阅读3分钟

这是我参与8月更文挑战的第7天,活动详情查看: 8月更文挑战

文本溢出隐藏,超出多少行,显示‘展示’按钮,点击更多显示全部

首先考虑一下要实现的结果:

  • 文本超出两行时显示省略号
  • '显示更多'按钮可以显示所有文本

初步实现方法:

  • 使用css属性line-clamp ,定义 被截断 文本的行数:
  • 获取高度判断是否需要展示'显示更多'字段

大概有思路后开始写代码:

html部分:

    <div class="content">
			<div class="text">
				<span>先帝创业未半,而中道崩殂;今天下三分,益州疲弊,此诚危急存亡之秋也!然侍卫之臣,不懈于内;忠志之士,忘身于外者,盖追先帝之殊遇,欲报之于陛下也。
						诚宜开张圣听,以光先帝遗德,恢弘志士之气﹔不宜妄自菲薄,引喻失义,以塞忠谏之路也。
						宫中、府中,俱为一体;陟罚臧否,不宜异同。若有作奸、犯科,及为忠善者,宜付有司,论其刑赏,以昭陛下平明之治;不宜偏私,使内外异法也。
						侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰「能」,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
						亲贤臣,远小人,此先汉所以兴隆也﹔亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也!侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之、信之,则汉室之隆,可计日而待也。
				</span>
			</div>
    </div>

css多行内容截断:

 .text span {
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
 } 

这样的话,会实现大概如下效果: 屏幕截图 2021-07-27 181527.png

然后,要实现的效果就是展示'显示更多'字段: 简单的方法就是添加一个标签 ,显示文字,点击后让css属性line-clamp的行数增加到足够大的行数,是的能够展示更多文字 这里可以使用js实现,看别人博客时看到一个用css的方法,这里来试试

监听按钮的点击行为则用input的 checked 伪类:

input[name="toggle"]:checked + span {
   -webkit-line-clamp: unset;
}	

html 标签改动

<div class="content">
	<div class="text">
		<input type="checkbox" id="toggle" name="toggle">
		<span>文本内容 。。。。。。</span>
		<label for="toggle"></label>
	</div>
</div>

这样简单的简单的点击展开更多,收起功能就实现了,但有一个问题,就是文本展示不对,同理使用伪类来进行赋值,我们把label的值去掉,使用伪类来赋值:

	input[name="toggle"]:checked + span ~label::after {content: '收起更多';	}
	label::after{content: '显示更多';}

这样展示,隐藏效果就实现了

我要把'显示更多'和'收起更多'放到文本末尾,而不是另起一行

好好好,首先想到的就是把laber定位到末尾

 label{color: cadetblue;position: absolute;right: 0;bottom: 0;z-index: 9;background: #000; }

这样子就实现了在文末展示'显示更多'的文本框,效果如下: 798fs-gx8qt.gif

本以为这下应该就没啥事了,结果又给找出了问题:'不对,你这文字没有超出多行,咋的还有‘显示更多’字段'?

大意了,确实考虑不周:赶紧想想解决方法:

 window.onload = function(){
		const textContent = document.getElementsByTagName("span");
		const labelBox = document.getElementsByTagName("label")[0]
		let {clientHeight,scrollHeight}  = textContent[0]
		console.log(clientHeight,scrollHeight);
		if(clientHeight < scrollHeight){
				labelBox.classList.add("have")
		}else{
				labelBox.classList.remove("have")
		}
	}

这样子就获取到了当前的未截断高度和当前截断时的高度:比较大小来判断是否展示label,动态的设置当前类名实现label的实现展示,效果可以说是非常好,本以为这样子就完事了。

给我提了一个非常细节的问题,你这个文字挡住半个,能不能让文字都展示出来啊?(如下图)脑壳爆炸:浏览了很多地方没看到效果要的结果,后来无意之中想到了一个方法,也怪自己学艺不精

屏幕截图 2021-07-28 105029.png 不过有一说一,这样子的效果确实真的很难看(写出来才敢这样说🐕)

解决方法

  • 使用js计算宽度,然后截取文字长度
  • 能不能使用文字环绕效果实现

首先第一种方法应该也是可行的,但是想到空格、换行等的计算感觉有点烦 第二种方法比较简单使用css就能实现,减少js计算所以来试试

  1. 先实现label环绕效果
  • 给label设置float,使之浮动的右侧 右浮动.png

效果是这样的

  • 添加额外的标签,设置浮动,宽度为0,高度为当前文本高度,然后留住label的位置
 .text::before { content: '';float: right; height: 100%; margin-bottom: -20px;width: 0; } 

这样子效果就达成了: 最终成果图.png

然后就是点击更多展开,点击收起,溢出部分省略号展示

  • 这部分的思路就是点击展示更多,去除webkit-line-clamp行数,由于改变了标签,这里对展开收起运用了js操作
check.addEventListener('change', function (e) {
		if (e.target.checked) {
				textContents.classList.remove("text")
		} else {
				textContents.classList.add("text")
		}
});

最终效果就实现了,具体效果如下: 1mcqq-zlner.gif

<!--
 * @Descripttion: 
 * @version: 
 * @Author: shijuwang
 * @Date: 2021-07-27 17:23:57
 * @LastEditors: shijuwang
 * @LastEditTime: 2021-08-07 15:09:41
-->

代码地址: >>> 项目查看

码字不易,希望大佬多多指点