之前写过这样一篇文章:CSS 实现多行文本“展开收起”,介绍了一些纯 CSS 实现多行文本展开收起的小技巧,非常巧妙,有兴趣的可以回顾一下。
不过展开收起按钮的隐藏和显示采用了“障眼法”,也就是通过一个伪元素设置和背景相同的颜色覆盖实现的,如下:
:时代在进步,CSS也在不断发展。 CSS 容器查询[1]出来也有一段时间了,能够动态判断容器尺寸,赶紧拿来用一下,发现并没有想象中的那么顺利,甚至还有些难用,一起看看吧
CSS 容器查询,顾名思义,就是可以动态查询到容器的尺寸,然后设置不同的样式。
比如有这样一个容器。
<div class="card"> <h2>欢迎关注前端侦探</h2></div>
简单美化一下。
.card{ display: grid; place-content: center; width: 350px; height: 200px; background-color: #FFE8A3; border-radius: 8px; border: 1px dashed #9747FF;}
效果如下:
现在这个容器宽度是 350px,现在希望在宽度小于 250px时文字颜色变为绿色,要怎么做呢?
非常简单,只需要规定一下容器的类型,然后写一个查询语句就行了,关键实现如下:
.card{ /**/ container-type: size;}@container (width < 250px){ .card h2{ color: #14AE5C; }}
这样在动态改变元素尺寸时就会自动改变颜色了,效果如下
是不是非常简单?
可事实是这样吗,其实还有很多局限。
主要是有两点局限。
第一点,容器查询不可更改容器本身样式,比如像这样,直接改颜色是不生效的。
.card{ /**/ container-type: size;}@container (width < 250px){ .card{ color: #14AE5C; }}
白白浪费了一层标签。
也无法通过:has去匹配父级。
.card{ /**/ container-type: size;}@container (width < 250px){ body:has(.card h2){ color: #14AE5C; }}
还有一点问题更大,容器必须手动指明尺寸,不可以由内容撑开,也就是自适应内容尺寸,比如我们将上面的宽高去除
可以看到,在设置成容器查询类型后,「容器的宽高都变成了 0」,必须手动设置宽高。
所以,在实际应用中,必须要想办法规避这两个问题。
现在回头看多行文本的例子,通过之前的文章,我们可以很“轻松”的实现这样一个布局,如果不太清楚的可以回顾一下,这里就不多描述了
<div class="text-wrap"> <div class="text-content"> <label class="expand"><input type="checkbox" hidden></label> 欢迎关注前端侦探,这里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。 </div></div>
相关样式如下:
.text-wrap{ display: flex; position: relative; width: 300px; padding: 8px; outline: 1px dashed #9747FF; border-radius: 4px; line-height: 1.5; text-align: justify; font-family: cursive;}.expand{ font-size: 80%; padding: .2em .5em; background-color: #9747FF; color: #fff; border-radius: 4px; cursor: pointer;}.expand::after{ content: '展开';}.text-content{ display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;}.text-content::before{ content: ''; float: right; height: calc(100% - 24px);}.expand{ float: right; clear: both; position: relative;}.text-wrap:has(:checked) .text-content{ -webkit-line-clamp: 999;}.text-wrap:has(:checked) .expand::after{ content: '收起';}
这样就得到了一个“右下角”可以展开收起的布局,不过目前按钮是始终可见的。
我们尝试用容器查询来判断一下:
.text-wrap{ /**/ container-type: size;}
结果...高度都变成了 0。
所以直接添加是不行的。
有什么办法可以让容器查询可以自适应内容高度呢?我这里想到的办法是,外层用一个自适应内容高度的容器,然后容器查询盒子用绝对定位的方式,高度跟随外层,原理如下:
因此,我们需要添加两层,一层作为自适应内容的容器,一层作为容器查询盒子,自适应内容的文本可以用伪元素来代替,和真实内容保持一致就行了。
<div class="text-wrap"> <div class="text" title="欢迎关注前端侦探,这里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。"> <div class="text-size"> <div class="text-flex"> <div class="text-content"> <label for="check" class="expand"><input type="checkbox" id="check" hidden></label> 欢迎关注前端侦探,这里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。 </div> </div> </div> </div> </div>
然后把.text-size座位容器查询盒子。
.text-size{ position: absolute; inset: 0; container-type: size;}@container (height <= 4.5em) { .text-size .expand{ display: none; }}
虽然现在有点乱,但容器查询已经生效了,在小于等于4.5em(3行)的时候,右下角按钮已经消失了。
如果隐藏占位伪元素,其实是这样的。
空出一大段空白确实不雅,由于我们需要查询的高度是最大高度,所以外层自适应高度不能再变了,相当于 JS 中的 scrollHeight,因此,这层容器需要设置绝对定位,从而不影响最外层容器。
.text{ position: absolute}
同时将占位伪元素隐藏后,效果如下:
现在高度都回到了0,因此我们需要额外一份文本来自适应最外层容器,而且也能展开收起。
<div class="text-wrap"> <div class="text" title="欢迎关注前端侦探,这里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。"> <div class="text-size"> <div class="text-flex"> <div class="text-content"> <label class="expand"><input type="checkbox" hidden></label> 欢迎关注前端侦探,这里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。 </div> </div> </div> </div> <div class="text-content text-place"> 欢迎关注前端侦探,这里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。 </div></div>
我们只需要它的高度,所以可以设置为不可见。
.text-place{ visibility: hidden;}
这样容器的高度其实是由text-place这一层撑开的,效果如下:
总算实现了动态查询自适应文本容器高度,效果如下:
还有很多细节,可以查看以下 demo。
总的来说,容器查询并没有想象中那么“好用”,甚至有些难用,也有可能使用过场景并不在这里,虽然最终勉强实现了,但是代价太大了,多了两份相同的文本内容,HTML
结构也复杂了好多。下面总结一下
仅仅作为尝试,实际并不推荐,最终结构还是过于复杂,3份相同的内容有些过于冗余,其实HTML结构实现到右下角按钮那里就可以了,动态高度还是交给 JS去判断吧。
[1]容器查询: https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Container_Queries。
[2]CSS @container clamp (juejin.cn): https://code.juejin.cn/pen/7312418754502066214。
[3]CSS @container clamp (codepen.io): https://codepen.io/xboxyan/pen/oNmRbvR。
本文链接:http://www.28at.com/showinfo-26-48343-0.html尝试借助CSS @container实现多行文本展开收起
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com