突發奇想!藉助CSS自定義彩色字型來實現多行文字展開收起

XboxYan發表於2023-03-27
歡迎關注我的公眾號:前端偵探

之前寫過這樣一篇文章:CSS 實現多行文字“展開收起”,介紹了一些純 CSS 實現多行文字展開收起的小技巧,特別是右下角的“展開收起”按鈕,用到了浮動佈局,非常巧妙,有興趣的可以回顧一下。

Kapture 2023-03-25 at 13.56.18.gif

原本以為已經很完美了,或者說是 CSS 的極限了。但是最近突然冒出一個想法,藉助自定義彩色字型也能完美實現這樣的效果,而且實現起來更加簡單,適用性和相容性也更強,一起看看吧

一、彩色字型

說到字型圖示,大家可能會想到一些平臺,比如 iconfontfontawesome 等。沒錯,我們今天要用到的就是iconfont

在之前一段時期,iconfont 支援了全新的彩色字型圖示,讓我們可以更加方便的建立自己的彩色字型。

彩色字型(colors fontschromatic fonts)是一種字型技術,它允許在每個字形中使用多種顏色。它不僅可以用在圖示和表情符號(emoji)的設計中,也可以用在普通的文字字型中

image.png

有興趣的可以參考這篇文章:iconfont 支援全新的彩色字型圖示 ,這裡就不多重複了。簡單來說,可以讓指定字元渲染成自定義字元,包括彩色圖案。

那麼,這和本文多行文字展開收起有什麼關係呢?

二、透過彩色字型自定義省略號

大家都知道多行文字,可以設定超出省略號

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

效果如下

image.png

雖然這個省略號是自動生成的,但也是真真正正的省略號,只是頁面上看不到而已

?

?

?

既然頁面無法找到這個省略號,那是不是可以透過字型改變他的外觀?比如做成展開按鈕?

image.png

說幹就幹,首先在繪圖工具上畫一個帶省略號的展開按鈕,下面是figma

image.png

然後將這個 SVG 圖示上傳到自己的專案中

image.png

上傳之後就是這樣

image.png

接下來,編輯圖示的字元或者Unicode,將這個圖示和省略號一一對應,比如省略號就是(注意,中文省略號其實是兩個英文省略號組成),或者直接寫它的Unicode2026,如下

image.png

儲存以後來到專案設定,把字型格式的“彩色”這一項給勾上,如果需要本地化可以勾上“Base64”

image.png

這樣準備工作就算完成了,可以透過線上連結得到線上使用方式,如下

image.png

最後,我們將這個字型引入到 CSS 中

@font-face {
  font-family: 'iconfont';  /* Project id 2593077 */
  src: 
       url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAARQAAwAAAAAB0wAAAQCAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIi4jGgZgAEQKh0yGHgE2AiQDFgsSAAQgBYF8ByAbtQXIHpIkUAoFJEQgAQAwBc/3+7Vz76qmTW9DUYm7mDXILNMtecQT3hgqZA/1J9RS+MO/p70snZKJVLdDcRD/VID/838u3iiApx9wIHsjm0jFZdo1RZXR8VEVVRkcMB7dsrrWEasO0IsHAAXCQApSS+cIZilOBBfgBi4yeDog4QdH7ZrGfy0f/p8EMP5CqM6udGoHSQiA4Wi8zKAoioAS1wACGI4ZGbUxBnvwpevhvP8AjjXA+e44ilrDhI19kNyei5Ix5AB4g28UMEaEv/7/JOP/86ePniQsIlOdl+qjiEqfYbfR6cTXyfUKBDdOJaEHhA5TqIPhJVfnUclMC65yhdaYm9FK1lYon6UFqWBqcoaOSlQ6j8skW7uNZm7dhcjz7yAZm7cyASou+HEA1OJevzLDOjeNMRFcEC6fVblxOCOe1lVRCIFQcgFYe8DptYywHBKJEEQN/ARI7EJ99Caw6wh/EEVgpA+Hs2qZYLkhEnnHeFrzoYkILShe9J/i5WeJrsgCnmm8+iaxDYIMzqlfEdF1hiDQNsWW7iRBoCWckkLrKCuMkoyuivLSQ6KrcdscGxp9ACvwa8fvo2hlay9v8zBzV98YglRsQJATw49opT/7FG1qY0IqCASZLhzbQesWia7KXVx47SsY0SOXEuD8Pq9XCIgHE5UAeGsDJgvLzoF9zMT85JqD/Rp7xAxgC8vBgRYmTAXnuN7ewNgfo0/YpwL1Mw4liU2JED8gydkEkmTg1wHvdJFRiVFxiHaJtlSKVbUVzdikcNZjF7pUFvVFKaNOh1wmE7TMaYiss6hlfw+eKHGSTDUKlAjUTudTQ8r4S5iDZwtgnmzy5fLBt4Eg7TiJOKNKyRemNDvBSY3rW+s5m3JNHAocm4Y8wYaex2HJxfG6ttyuWl1yPWQ05H0lsoKyeVsg8g8euxaN28NKxIXpi9HbKRU7f7DS+5XSZ05Q/s99Q5sQBTXOkHBZPdsusZD3Z5s/XKZLDOUWt5zY2UF9d8FZ1tz40jlTjm1Bu4nBgT2K4uS3wVTFodTPn3L0VdN0Z6zRNB+h5AsnAzp3XnInyVKJ36+fKb2wIM8gyqZmcVR9dxJ/TbsMJnJVLgxGH516EufpW4HbP60kk3H9n0qpXOcYyRgLWYtIyUjnbKnEgCipG8/jkvGy4Wtf2tZvCvgxhD5nORuj6ibw0ObHwnk/gjhBeLMTBY7BQ6782LcmvFc/Tjqtjg4MYOYxi0PiXvYg27ilv9zNCDDipARC9N9hM1XBEAXgoAIPcGJwAi5SJB1yY6ghnEBiiSGEn5eEA8GEkkwU/iQgjwxyQUwTG2xRNU5aDh8lrbXsIuPzuBDMfYmEwyDfBl0taoPx6exFFAEA') format('woff2'),
       url('//at.alicdn.com/t/font_2593077_78ql8ytgk.woff?t=1632398100463') format('woff'),
       url('//at.alicdn.com/t/font_2593077_78ql8ytgk.ttf?t=1632398100463') format('truetype');
}
.text{
  font-family: 'iconfont';
}

這樣,剛才的省略號就變成了這個圖示

image.png

由於省略號只是換了個字型,所以當預設省略號消失的時候,這個按鈕跟著消失,比如下面是文字較少的時候

image.png

這樣就無需藉助浮動佈局了,並且也能自動隱藏,是不是非常完美?

三、點選展開收起

雖然上面實現了展開按鈕,但是是假的,還沒有任何點選行為。接下來需要藉助input checkbox來實現展開收起行為,原理和之前一樣,下面是HTML

<div class="wrapper">
    <input id="exp" class="exp" type="checkbox" hidden>
    <div class="text">歡迎關注前端偵探,這裡有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧,比如這篇文章,透過iconfont自定義彩色字型來實現多行文字展開收起,一起看看吧</div>
    <label class="btn" for="exp"></label>
</div>

因為視覺上已經有展開按鈕了,所以這裡的label只需要定位在右下角就行了,並且設定透明度為0,目的是保留點選行為

.btn{
    position: absolute;
    right: 10px;
    bottom: 10px;
    opacity: 0; /*設定透明度為0*/
    cursor: pointer;
}

效果如下

image.png

然後透過:checked控制文字行數

:checked+.text{
    -webkit-line-clamp: 999;
}

這樣就可以展開了

Kapture 2023-03-25 at 15.28.30.gif

由於label是隱藏的,所以在展開以後按鈕也就不可見的,其實還是在右下角

image.png

因此,我們可以將這個label本身設定成收起的樣式,在展開後顯示就可以了,這裡採用的也是彩色字型

:checked~.btn{
    opacity: 1;
}

這樣就簡單實現了展開收起

Kapture 2023-03-25 at 15.33.22.gif

四、文字較少時阻止點選

上面的實現在文字較多時很完美,在文字較少時會有點問題。

由於label按鈕是定位在右下角的,所以無論文字多少,始終都是可以點選的,如下

image.png

雖然看不見,但可以點選,點選以後,收起按鈕就出現了

Kapture 2023-03-25 at 15.43.00.gif

雖然不影響功能,但視覺上還是難以接受,有沒有辦法阻止這個按鈕呢?

這下又需要用一些“障眼法”了,可以用一層足夠大容器在文字較少時遮罩右下角的按鈕,這裡可以用偽元素生成

.text::after{
    content: '';
    position: absolute;
    width: 100vw;
    height: 100vw;
    z-index: 10;
}

注意,這裡絕對定位不需要給定偏移量,這樣偽元素會跟隨文字,也就是當文字沒有超過指定行數時,偽元素就會完全覆蓋右下角,如下

關於這個絕對定位的小技巧可以參考之前這篇文章:你可能不知道的絕對定位

image.png

這樣在文字較少時就可以覆蓋右下角的label按鈕,無法點選

Kapture 2023-03-25 at 16.00.21.gif

當然,這個背景是不需要的,完全透明的也行,目的只是阻止點選而已,下面是最終效果

Kapture 2023-03-25 at 16.02.08.gif

下面是完整程式碼,相比之前的實現要少不少

.text {
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: justify;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-height: 1.5;
    font-family: iconfont;
}
.text::after{
    content: '';
    position: absolute;
    width: 100vw;
    height: 100vw;
    z-index: 10;
}
.btn{
    position: absolute;
    right: 10px;
    bottom: 10px;
    opacity: 0;
    cursor: pointer;
    font-family: iconfont;
    line-height: 1.5;
}
.exp:checked+.text{
    -webkit-line-clamp: 999;
}
.exp:checked+.text::after{
    visibility: hidden;
}
.exp:checked~.btn{
    opacity: 1;
}

你也可以訪問以下任意連結

五、總結和說明

以上就透過自定義彩色字型實現了多行文字展開收起的功能,相比之前的實現,除了實現上跟簡潔之外,還有個比較大的優勢在於對於背景沒有要求,而不僅僅是純色,如下

image.png

這種效果在之前的實現中是無法做到的,下面總結一下實現要點:

  1. 時代在變化,技術也在變化,思維也在變化,以前實現的功能可能會有更好的解決方案
  2. 整體思路其實是將預設的省略號自定義成了一個帶展開按鈕樣式的彩色字型
  3. 這樣的好處是無需藉助佈局,然後實現了右下角展開按鈕和按鈕的自動隱藏
  4. 用一層足夠大容器設定絕對定位可以在文字較少時遮罩右下角的按鈕
  5. 相容性極佳,支援彩色字型即可,理論上相容到 IE9+

整體實現還是非常簡單的,只是一般情況下不容易想到,當初 iconfont 宣佈支援彩色字型時也沒有想到這種應用場景,所以需要一點點想象力。

對了,還有一些小細節,因為改變了省略號的字型,所以如果文字中本身包含有省略號就會變成這樣

image.png

當然這個問題也比較好處理,因為文字中的內容是可控的,所以只需要提前用JS將文字內容處理一下,比如給省略號包裹一層標籤

text.innerHTML = text.textContent.replace(/(…)/g, '<span>$1</span>')

然後給這個標籤設定其他字型就行了

.text span{
  font-family: system-ui;
}

這樣就正常了~

image.png

最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤

歡迎關注我的公眾號:前端偵探

相關文章