嘗試借助CSS @container實(shí)現(xiàn)多行文本展開收起
之前寫過這樣一篇文章:CSS 實(shí)現(xiàn)多行文本“展開收起”,介紹了一些純 CSS 實(shí)現(xiàn)多行文本展開收起的小技巧,非常巧妙,有興趣的可以回顧一下。
不過展開收起按鈕的隱藏和顯示采用了“障眼法”,也就是通過一個偽元素設(shè)置和背景相同的顏色覆蓋實(shí)現(xiàn)的,如下:
:時代在進(jìn)步,CSS也在不斷發(fā)展。 CSS 容器查詢[1]出來也有一段時間了,能夠動態(tài)判斷容器尺寸,趕緊拿來用一下,發(fā)現(xiàn)并沒有想象中的那么順利,甚至還有些難用,一起看看吧
一、簡單介紹一下容器查詢
CSS 容器查詢,顧名思義,就是可以動態(tài)查詢到容器的尺寸,然后設(shè)置不同的樣式。
比如有這樣一個容器。
<div class="card">
<h2>歡迎關(guān)注前端偵探</h2>
</div>
簡單美化一下。
.card{
display: grid;
place-content: center;
width: 350px;
height: 200px;
background-color: #FFE8A3;
border-radius: 8px;
border: 1px dashed #9747FF;
}
效果如下:
現(xiàn)在這個容器寬度是 350px,現(xiàn)在希望在寬度小于 250px時文字顏色變?yōu)榫G色,要怎么做呢?
非常簡單,只需要規(guī)定一下容器的類型,然后寫一個查詢語句就行了,關(guān)鍵實(shí)現(xiàn)如下:
.card{
/**/
container-type: size;
}
@container (width < 250px){
.card h2{
color: #14AE5C;
}
}
這樣在動態(tài)改變元素尺寸時就會自動改變顏色了,效果如下
是不是非常簡單?
可事實(shí)是這樣嗎,其實(shí)還有很多局限。
二、容器查詢的局限
主要是有兩點(diǎn)局限。
第一點(diǎn),容器查詢不可更改容器本身樣式,比如像這樣,直接改顏色是不生效的。
.card{
/**/
container-type: size;
}
@container (width < 250px){
.card{
color: #14AE5C;
}
}
白白浪費(fèi)了一層標(biāo)簽。
也無法通過:has去匹配父級。
.card{
/**/
container-type: size;
}
@container (width < 250px){
body:has(.card h2){
color: #14AE5C;
}
}
還有一點(diǎn)問題更大,容器必須手動指明尺寸,不可以由內(nèi)容撐開,也就是自適應(yīng)內(nèi)容尺寸,比如我們將上面的寬高去除
可以看到,在設(shè)置成容器查詢類型后,「容器的寬高都變成了 0」,必須手動設(shè)置寬高。
所以,在實(shí)際應(yīng)用中,必須要想辦法規(guī)避這兩個問題。
三、多行文本展開收起中的應(yīng)用
現(xiàn)在回頭看多行文本的例子,通過之前的文章,我們可以很“輕松”的實(shí)現(xiàn)這樣一個布局,如果不太清楚的可以回顧一下,這里就不多描述了
<div class="text-wrap">
<div class="text-content">
<label class="expand"><input type="checkbox" hidden></label>
歡迎關(guān)注前端偵探,這里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。
</div>
</div>
相關(guān)樣式如下:
.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;
}
結(jié)果...高度都變成了 0。
所以直接添加是不行的。
有什么辦法可以讓容器查詢可以自適應(yīng)內(nèi)容高度呢?我這里想到的辦法是,外層用一個自適應(yīng)內(nèi)容高度的容器,然后容器查詢盒子用絕對定位的方式,高度跟隨外層,原理如下:
因此,我們需要添加兩層,一層作為自適應(yīng)內(nèi)容的容器,一層作為容器查詢盒子,自適應(yīng)內(nèi)容的文本可以用偽元素來代替,和真實(shí)內(nèi)容保持一致就行了。
<div class="text-wrap">
<div class="text" title="歡迎關(guān)注前端偵探,這里有一些有趣的、你可能不知道的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>
歡迎關(guān)注前端偵探,這里有一些有趣的、你可能不知道的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;
}
}
雖然現(xiàn)在有點(diǎn)亂,但容器查詢已經(jīng)生效了,在小于等于4.5em(3行)的時候,右下角按鈕已經(jīng)消失了。
如果隱藏占位偽元素,其實(shí)是這樣的。
空出一大段空白確實(shí)不雅,由于我們需要查詢的高度是最大高度,所以外層自適應(yīng)高度不能再變了,相當(dāng)于 JS 中的 scrollHeight,因此,這層容器需要設(shè)置絕對定位,從而不影響最外層容器。
.text{
position: absolute
}
同時將占位偽元素隱藏后,效果如下:
現(xiàn)在高度都回到了0,因此我們需要額外一份文本來自適應(yīng)最外層容器,而且也能展開收起。
<div class="text-wrap">
<div class="text" title="歡迎關(guān)注前端偵探,這里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。">
<div class="text-size">
<div class="text-flex">
<div class="text-content">
<label class="expand"><input type="checkbox" hidden></label>
歡迎關(guān)注前端偵探,這里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。
</div>
</div>
</div>
</div>
<div class="text-content text-place">
歡迎關(guān)注前端偵探,這里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧。
</div>
</div>
我們只需要它的高度,所以可以設(shè)置為不可見。
.text-place{
visibility: hidden;
}
這樣容器的高度其實(shí)是由text-place這一層撐開的,效果如下:
總算實(shí)現(xiàn)了動態(tài)查詢自適應(yīng)文本容器高度,效果如下:
還有很多細(xì)節(jié),可以查看以下 demo。
- CSS @container clamp (juejin.cn)[2]
- CSS @container clamp (codepen.io)[3]
四、總結(jié):容器查詢還是不太適合
總的來說,容器查詢并沒有想象中那么“好用”,甚至有些難用,也有可能使用過場景并不在這里,雖然最終勉強(qiáng)實(shí)現(xiàn)了,但是代價太大了,多了兩份相同的文本內(nèi)容,HTML
結(jié)構(gòu)也復(fù)雜了好多。下面總結(jié)一下
- 容器查詢可以根據(jù)容器的尺寸匹配不同的樣式。
- 容器查詢并沒有那么“好用”,有兩個局限性。
- 一個是容器查詢不可更改容器本身樣式,導(dǎo)致白白浪費(fèi)一層標(biāo)簽。
- 還有一個是容器必須手動指明尺寸,不可以由內(nèi)容撐開,也就是自適應(yīng)內(nèi)容尺寸,否則容器尺寸就是 0。
- 為了規(guī)避容器查詢的局限性,使用一層額外的文本充當(dāng)容器查詢。
- 使用另一層額外的文本來撐開最外層容器。
僅僅作為嘗試,實(shí)際并不推薦,最終結(jié)構(gòu)還是過于復(fù)雜,3份相同的內(nèi)容有些過于冗余,其實(shí)HTML結(jié)構(gòu)實(shí)現(xiàn)到右下角按鈕那里就可以了,動態(tài)高度還是交給 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。