純 CSS 自定義多行省略:從原理到實現

文字溢出怎麼展示,你的需求是什麼?單行還是多行?截斷,省略,自定義樣式,自適應高度?在這裏你都能找到答案。接下來我會由淺入深,從原理到實現,帶你一步步揭開多行省略的面紗。我們先從最簡單的單行溢出省略開始,

熱身,單行省略

這是一個全宇宙統一的方案,沒有太多的魔法,戳我查看示例 [1]

/* 原理:設置文字不換行,溢出後隱藏,截斷顯示省略符 */
.ellipsis {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
複製代碼

如何實現多行省略呢?先從最簡單的 line-clamp 開始吧。

最簡單的多行省略,line-clamp

通過 CSS 屬性 -webkit-line-clamp 可以把塊容器中的內容限制爲指定的行數,示例 [2]

.ellipsis {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
複製代碼

屬性的 -webkit 前綴告訴我們事情似乎並不簡單。是的,它只支持基於 webkit 內核的瀏覽器,這對於移動端是很友好的,在 安卓 2.3+,IOS 5.0+ 的設備上你可以直接將上述代碼直接扔進去沒啥問題,但如果要在 PC 端使用,需要關注下兼容性問題,

除了 PC 兼容性問題,line-clamp 的方案也不支持自定義省略樣式,如果需要在省略符後面加文字,箭頭等自定義樣式,我們可能就得考慮其他方案了,比如:浮動

神奇的 float,浮動

什麼!浮動也能實現多行省略?是的,下面我們用三個浮動盒子來模擬多行省略。首先準備三個盒子(文字盒,佔位盒,自定義樣式的省略盒)向右浮動,爲了方便理解原理,我們給盒子增加不同的背景色,

<div class="box">
  <!-- 文字盒子 -->
  <div class="box__text">騰訊以技術豐富互聯網用戶的生活。通過通信及社交軟件微信和 QQ 促進用戶聯繫,並助其連接數字內容和生活服務,盡在彈指間。</div>
  <!-- 佔位盒子 -->
  <div class="box__placeholder"></div>
  <!-- 自定義省略盒子 -->
  <div class="box__more">...展開</div>
</div>

<style>
  .box__text {
    width: 100%;
    height: 60px;
    line-height: 20px;
    background-color: pink;
    float: right;
  }

  .box__placeholder {
    width: 60px;
    height: 60px;
    background-color: gray;
    opacity: 0.8;
    float: right;
  }

  .box__more {
    width: 60px;
    text-align: right;
    background: yellow;
    float: right;
  }

</style>
複製代碼

接下來開始調整位置,先給文字盒一個負的左外邊距,它的值剛好爲佔位盒的寬度

.box__text {
  margin-left: -60px;
}
複製代碼

這樣一來就給了佔位盒子空間,它會浮動到左邊,和文字盒排在一排,

上圖中,文字盒的高度小於佔位盒高度,此時第一排高度爲佔位盒子高度,第一排沒有多餘空間,我們自定義的省略盒子只能排在第二排。試想一下,當文字盒的高度大於佔位盒高度時(比如文字顯示 4 行),會發生什麼?

第一排的高度會被文字盒撐開,這個時候第一排有了多餘空間,省略盒子能夠擠進去。

Awesome 😊,接下來只需要把省略盒子定位到右邊和佔位盒子同排的位置就可以了,

.box__more {
  position: relative;
  left: 100%;
  transform: translate(-100%, -100%);
}
複製代碼

修飾一下,去掉背景色,容器設置溢出隱藏,然後給省略盒子加個文字顏色和漸變,

.box {
  position: relative;
  overflow: hidden;
}

.box__more {
  color: #1890ff;
  background-image: linear-gradient(to left, white 40%, rgba(255, 255, 255, 0.8) 70%, transparent 100%);
}
複製代碼

效果還不錯,想要完整示例,戳我查看 [3]。

小結一下,這裏其實運用了浮動和 BFC 的原理。(如果你還不瞭解 BFC 可以去看一下我之前的文章 《可能是最好的 BFC 解析了...》[4],裏面有非常全面的解析)

外層盒子通過 overflow: hidden 創建一個 BFC,浮動盒子的區域不會和 BFC 重疊,計算 BFC 高度時,浮動元素也會參與計算,浮動盒會浮動到當前行的開頭或結尾,再借助一些定位技術,就可以模擬多行省略的效果了。

浮動的方案的優勢非常明顯,

由於省略樣式區域本質上是一個浮動盒子,所以這裏我們需要通過漸變來防止穿幫,對於某些背景顏色比較複雜的區域,或者更強的一些自定義省略樣式需求時(比如省略樣式定義爲一張箭頭或圖片等),這種方案開始顯得力不從心了。

有沒有其他方式可以實現省略樣式完全的自定義呢?

有,將自定義省略盒子的位置預留出來

那要怎麼預留呢?我們可以藉助 line-clamp。由 line-clamp 截斷後的省略號 ... 剛好可以幫助我們進行佔位,如果我們能通過某種辦法將默認的省略號隱藏掉,再替換爲我們自定義的浮動盒子,是不是就可以了!這也就是接下來我們要介紹的方案。

完全自定義,浮動 + line-clamp

我們重新整理一下上述的思路,關鍵的點有三個,

  1. 藉助 line-clamp 默認的省略號,預留自定義省略盒子的位置

  2. 想辦法隱藏默認省略號

  3. 通過定位技術替換預留位置爲我們自定義的省略盒子

逐一來看,首先是預留位置,line-clamp 默認省略號的大小受字號 font-size 的影響,所以調整字號就可以控制預留位置的大小。這裏爲了保證省略號的大小隻受字體大小的影響,我們可以重置行高和文字間距,

.box__text {
  position: relative;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  font-size: 60px;
  line-height: 0;
  letter-spacing: 0; /* 重置了行高和文字間距,保證省略號佔位只受字體大小的影響 */
  color: red; /* 爲了方便演示,我們先給省略號一個顏色 */
}
複製代碼

這樣就可以通過只調整文字盒子的字號,來控制預留省略盒子位置的大小了。由於 font-size 會繼承,所以我們再內嵌一個子盒子來重置字號,

<div class="box__text">
    <div class="box__inner">
      騰訊以技術豐富互聯網用戶的生活。通過通信及社交軟件微信和 QQ 促進用戶聯繫,並助其連接數字內容和生活服務,盡在彈指間。
    </div>
</div>

<style>
  .box__inner {
    font-size: 16px;
    line-height: 20px;
    color: #000;
    vertical-align: top;
    display: inline;
  }
</style>
複製代碼

接下來是想辦法隱藏省略號,這個比較簡單,可以設置透明度或者顏色透明,

.box__text {
  opacity: 0;
  color: transparent;
}
複製代碼

有了省略號的預留位置後,我們要想辦法將自定義省略盒子定位到預留位置,怎麼辦呢?還是 浮動。由於設置了 -webkit-line-clamp,會導致文字盒子無法撐開完整的高度,爲了使用浮動來實現定位,我們可以多渲染一份文案用來撐開高度。

準備一個絕對定位的盒子,作爲渲染撐開高度文案的容器,

<div class="box__abs">
    <div class="box__fake-text">
      騰訊以技術豐富互聯網用戶的生活。通過通信及社交軟件微信和 QQ 促進用戶聯繫,並助其連接數字內容和生活服務,盡在彈指間。
    </div>
    <div class="box__placeholder"></div>
    <div class="box__more">... 展開</div>
</div>

<style>
  .box__abs {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
  }
</style>
複製代碼

接着用我們前面講的三個浮動盒子實現多行溢出省略的方式,

.box__fake-text {
  width: 100%;
  margin-left: -60px;
  line-height: 20px;
  float: right;
  color: transparent; /* 文案是爲了撐開高度,配合浮動實現多行溢出省略 */
}

.box__placeholder {
  width: 60px;
  height: 60px;
  float: right;
}

.box__more {
  position: relative;
  left: 100%;
  transform: translate(-100%, -100%);
  width: 60px;
  text-align: right;
  color: #1890ff;
  float: right;
}
複製代碼

需要注意的是,這裏的文字盒子是爲了撐開高度,不需要展示,所以我們設置了顏色透明。好了,最後一步,去掉背景色,外層盒子設置溢出隱藏就是我們的最終效果,

戳我查看示例 [5]

line-clamp + 浮動的方式可以實現省略符完全自定義,我們重置了行高和文字間距,只需要調整外層盒子的字體大小 font-size 就可以控制自定義省略盒子的寬度,你可以將省略盒子替換爲任意的箭頭,圖片,折角或文字,這下再也不用擔心 UI 小姐姐提需求了 ):

寫在最後

本文首發於我的 博客 [6],才疏學淺,難免有錯誤,文章有誤之處還望不吝指正!

如果有疑問或者發現錯誤,可以在評論區進行提問和勘誤,

如果喜歡或者有所啓發,歡迎 star,對作者也是一種鼓勵。

(完)

參考資料

[1]

https://codepen.io/lycheelee/pen/abJvJXg: https://link.juejin.cn?target=https%3A%2F%2Fcodepen.io%2Flycheelee%2Fpen%2FabJvJXg

[2]

https://codepen.io/lycheelee/pen/KKWzWWg?editors=1100: https://link.juejin.cn?target=https%3A%2F%2Fcodepen.io%2Flycheelee%2Fpen%2FKKWzWWg%3Feditors%3D1100

[3]

https://codepen.io/lycheelee/pen/PopNmwz?editors=1100: https://link.juejin.cn?target=https%3A%2F%2Fcodepen.io%2Flycheelee%2Fpen%2FPopNmwz%3Feditors%3D1100

[4]

https://juejin.cn/post/6960866014384881671: https://juejin.cn/post/6960866014384881671

[5]

https://codepen.io/lycheelee/pen/xxdxwer: https://link.juejin.cn?target=https%3A%2F%2Fcodepen.io%2Flycheelee%2Fpen%2Fxxdxwer

[6]

https://github.com/campcc/blog: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fcampcc%2Fblog

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/CMH_EFGSvtVgioTV7gn6iA