CSS 實現文字"不定行數"截斷

XboxYan發表於2021-10-26

偶然發現,在某乎熱榜頁有一個很有意思的佈局,這裡的標題會制約內容的行數,所以文字超出是"不定行"的。詳細規則如下:

  1. 整個容器高度是固定的,標題和內容總共 3 行
  2. 標題最多2行,超出省略
  3. 內容由剩餘空間決定,如果標題佔2行,則內容超出1行省略;如果標題佔1行,則內容超出2行省略

是不是很靈(離)活(譜)的互動?可以充分利用頁面空間,保證標題和內容都能展示出來,示意如下

image-20211022112416841

看了下原站的實現,是通過 js 判斷標題高度,然後動態新增一個類名實現的。不過呢,經過一番琢磨,這裡也是可以純 CSS 實現的,一起來看看吧

一、標題超出省略

假設有這樣一段 HTML

<div class="section">
    <h3 class="title">LGD 在 TI10 放猛獁,RNG 在 S7 放加里奧最後都輸了,哪個更讓你憤怒失望?</h3>
    <p class="excerpt">猛獁是對面的絕中絕,大家都知道,並且之前扳回兩局已經證明了,當lgd選擇ban掉猛獁,或者自己搶掉猛獁時,對面完全不是對手。</p>
</div>

標題的規則是超出2行省略,這個簡單,直接用-webkit-line-clamp 實現

.title{
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

超出2行就會自動省略了

Kapture 2021-10-22 at 14.09.26

二、內容自適應行數

由於整個高度是固定的,如果讓內容部分自適應剩餘空間是不是就實現了呢?提到自適應剩餘空間,可以馬上想到 flex 佈局,所以可以這樣來實現:

.section{
    display: flex;
    overflow: hidden;
    height: 72px;/*定一個高度*/
    flex-direction: column;
}
.excerpt{
      flex: 1; /*自適應剩餘空間*/
      overflow: hidden;
}

這樣藉助flex: 1;overflow: hidden;就幾乎實現了想要的效果,如下

Kapture 2021-10-22 at 14.22.05

已經很完美,只是現在超出還沒有省略號,接著往下看

三、不定行超出省略

一般情況,-webkit-line-clamp適用於行數確定的情況下,現在行數不定,有時是 1 行,有時是 2 行,如何處理呢?這裡就需要一些奇技淫巧了。大家可能還記得這篇文章 CSS 實現多行文字“展開收起”,裡面就提到了如何使用浮動來實現文字超出省略的效果,有興趣的可以參考一下。

1. 右下角環繞效果

首先新增一個偽元素,設定右浮動

.excerpt::before{
    content: '...';
    float: right;
}

image-20211022143914085

很明顯省略號目前是在右上角的,現在需要挪到右下角來,之前的操作是通過一個浮動元素把這個省略號擠下來,但是需要額外的佔位元素

這裡再介紹一種新的方式,藉助 CSS shapes 佈局實現!

首先,將省略號高度撐滿,並居下對齊,可以用 flex 實現

.excerpt::before{
    content: '...';
    float: right;
      height: 100%;
    display: flex;
    align-items: flex-end;
}

image-20211022144434028

這樣省略號雖然到了右下角,但是上面的部分也被擠走了,沒有達到環繞的效果。這時就可以用 shapes 佈局了,不瞭解這個佈局的,可以參考一下 張鑫旭 的這篇文章: 寫給自己看的CSS shapes佈局教程 « 張鑫旭-鑫空間-鑫生活 (zhangxinxu.com)

這裡僅僅只需要利用到 shape-outside:inset()就可以了,表示以自身為邊界,然後上、右、下、左四個方向分別向內縮排的距離。比如這裡需要縮排到靠近省略號位置,所以

.excerpt::before{
    /*其他樣式**/
      shape-outside: inset(calc(100% - 1.5em) 0 0);
}

效果如下

Kapture 2021-10-22 at 14.56.46

去除背景,可以看到省略號完美的環繞在右下角

Kapture 2021-10-22 at 15.23.18

2. 自動隱藏省略號

現在還有一個問題,需要文字較少時隱藏省略號,該如何實現呢?可以試試 “CSS 障眼法”

簡單來說,就是用一個足夠大的色塊蓋住省略號,設定絕對定位後,色塊是跟隨內容文字的,所以在文字較多時,色塊也跟隨文字擠下去了,實現如下

.excerpt::after{
    content: '';
    position: absolute;
    width: 999vh;
    height: 999vh;
    background: #fff;
} 

原理示意如下

Kapture 2021-10-22 at 15.41.15

個別極端情況可能會遮擋不住,比如

image-20211025112119129

沒關係,可以隨便找個東西補上,比如 box-shadow,往左下角偏移一點就可以了

.excerpt::after{
    content: '';
    position: absolute;
    width: 999vh;
    height: 999vh;
    background: #fff;
      box-shadow: -2em 2em #fff; /*左下的陰影*/
} 

image-20211025112648385

設定和底色相同的顏色後,最終的效果如下

Kapture 2021-10-22 at 15.46.18

這樣就實現了文章開頭某乎的互動效果,完整程式碼可訪問 auto-clamp (codepen.io)

image-20211022183643368

四、總結和說明

以上實現了一個不定行數的文字截斷效果,融合了許多 CSS 小技巧,除了 shapes 佈局以外(當然也可以採用其他方式實現),沒有太多陌生的屬性,下面簡單總結一下:

  1. 多行省略直接使用 -webkit-line-clamp,現代瀏覽器都支援
  2. flex 佈局可以很方便的處理剩餘空間
  3. float + shapes 佈局也可以實現右下角環繞效果
  4. box-shadow 在障眼法中很常見
  5. 適當積累一些 CSS 奇技淫巧,有時候會幫上大忙

在我看來,佈局的事情當然最好由 CSS 解決,實現更靈活,渲染更迅速,沒有框架限制,無需等待 dom 載入,無需 JS 計算尺寸,無需遍歷節點,好處太多了。如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤

相關文章