如何用css实现多行文本加载更多
前言
之前我在实现该功能的时候专门封装了一个组件用js的状态来控制显示内容,而且由于切换按钮一直存在导致体验也不好,虽然可以用js判断是否超出来控制切换按钮的显隐,但总归是麻烦的。
我们要实现的大概效果如下图所示:
当超过设定行数时:
当未超过行数时:
思路
问题的关键点其实在于判断是否超过行数,未超过行数时需要隐藏切换按钮。
至于点击切换按钮显示全部行内容,这个通过input的切换状态就可以完成。
还有一个要求就是尽量保持HTML的语意化,因为使用input来切换通常会造成结构有点难以理解。
我们先确定大概的文档结构:
<article class="ac-article">
<h2>标题</h2>
<section>
这里有很多内容………………
</section>
<div class="switch">
<label>
<span>^</span>
<input type="checkbox" name="switch" />
</label>
</div>
</article>
这个结构是很清晰的,符合从上到下的内容设置。那么对应的css我们设置如下:
/* 设置一个基本的背景颜色,方便阅读 */
:root {
--section-color: #ECEEF0;
}
.ac-article {
background-color: var(--section-color);
border-radius: 6px;
padding: 10px;
}
.ac-article h2 {
text-align: center;
}
/* 设置多行省略,在这里可以设置一些属性选择器来设置line-clamp */
.ac-article section {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.ac-article .switch {
display: flex;
justify-content: center;
align-items: center;
}
.ac-article .switch label{
transform: translateY(30%);
font-size: 24px;
cursor: pointer;
font-family: monospace;
}
/* input默认隐藏,通过label触发 */
.ac-article .switch label input[name="switch"] {
display: none;
}
/* 这里因为用了^来表示按钮,所以在切换时通过rotate来变化状态 */
.ac-article .switch label:has(input[name="switch"]:checked) {
transform: rotate(180deg) translateY(0%);
}
/* 在切换按钮时设置行数为一个较大的值,这样自然就可以展开内容了 */
.ac-article:has(input[name="switch"]:checked) section {
-webkit-line-clamp: 9999;
}
到这里,其实我们已经完成了切换显示全部内容的功能。
实际效果如下:
剩下就是考虑怎么在行数较少的情况下,将切换按钮隐藏。
第一点,css中没有判断行数的伪类,我们想要隐藏是不太可能了,只可能盖住切换按钮,让它看起来“隐藏”了。
所以我们大概的思路就是在section元素里面加一个::after伪类,设置为block,这样它可以一直在section的尾行,当行数较多时,它会在底部,当行数较少时,它就直接覆盖切换按钮。
看起来是这样(橙色的是伪类):
在行数较少时,可以看到达到了我们的目标,盖住了切换按钮。
但也可以看到after伪类会超出显示,因为我们还没有设置section的position为relative。然后我们设置section的position为relative,使伪类只能在section中显示。
但是这样的话::after会因为overflow:hidden被隐藏,反而起不到效果。
而我们通过overflow:hidden的定义得知:
如果需要,内容将被裁减以适应边距(padding)盒。不提供滚动条,也不支持允许用户滚动(例如通过拖拽或者使用滚轮)。内容可以以编程的方式滚动(例如,通过设置
scrollLeft等属性的值或scrollTo()方法), 因此该元素仍然是一个滚动的容器。
判断的边界是padding,所以我们将section的底部padding设置为切换按钮的高度,然后将切换按钮设置margin为负高度值。
/* section设置底部padding */
.ac-article section {
position: relative;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
/*+++++*/
padding-bottom: 28px;
}
/* section伪类,为了凸显设置为橙色背景 */
.ac-article section::after {
position: absolute;
display: block;
content: '';
width: 100%;
height: 28px;
/* background-color: var(--section-color); */
background-color: #ee8262;
z-index: 3;
}
/* 设置切换按钮负margin,并设置zIndex小于after伪类,这样才能盖住 */
.ac-article .switch {
display: flex;
justify-content: center;
align-items: center;
/*++++*/
margin-top: -28px;
position: relative;
z-index: 2;
background-color: var(--section-color);
}
设置完如下:
可以看到已经实现了效果,接下来我们只要替换掉颜色,并且保证在切换按钮点击状态下不被::after覆盖即可
.ac-article section::after {
position: absolute;
display: block;
content: '';
width: 100%;
height: 28px;
/*++*/
background-color: var(--section-color);
/*++*/
z-index: 3;
}
.ac-article:has(input[name="switch"]:checked) section::after {
visibility: hidden;
}
完整代码效果演示如下:
参考链接: developer.mozilla.org/zh-CN/docs/…
--分割线--2024/02/19
在移动端上特殊场景会有一些问题,建议在pc上使用。