之前遇見一個問題,就是處理文字截斷,然後可以手動切換文字是全展示和手動展示,因為這個問題比較常見,而且其實現方式有多種,於是決定總結一下,與讀者分享。
前言
首先,我們看這樣一個場景:
其html 結構如下:
<p class="text-slice">
鄭成月的經歷就是一部中國社會歷史!很有價值的!不管是社會研究還是真心糾錯,都是非常好的案例。歷史就是用各種個人經歷寫成的,那樣就很有實在感。作家們沒有素材?都在書寫歌功頌德之文?想要把自己的作品流傳後世,這就是最好的素材
</p>
<label class="expand-more">更多</label>複製程式碼
樣式如下:
.text-slice {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
}複製程式碼
如圖,我們對文字預設展示內容有限制:限制預設最多顯示三行,未超出三行時不需要展示更多按鈕;超出內容被截斷時,可以點選更多,展示全部內容,此時更多文字變成取消,再次點選的時候文字收起。
實現上述功能,常見的是使用JavaScript,本文將介紹使用JavaScript和CSS共三種方式實現:
- Js實現
- CSS :target偽類 實現
- CSS :checked偽類 + ~(臨近兄弟節點選擇符)實現
Js實現
先從最常見的Js實現,通常我們繫結點選事件實現切換文字截斷與展示全部:
<script>
$(function() {
var $para = $('.content');
var $more = $('.expand-more');
$more.on('click', function() {
$para.toggleClass('text-slice');
if ($para.hasClass('text-slice')) {
$more.html('更多');
} else {
$more.html('收起');
}
});
});
</script>複製程式碼
如上,給按鈕繫結點選事件,在事件回撥中為文字切換實現截斷樣式的類名,並同時修改按鈕文字,很簡單。
但是,到目前為止我們應該發現一個問題吧,假如文字內容少於三行或者剛好三行,我們怎麼判斷是否需要展示切換按鈕呢?
思考。。。。。。
要判斷文字是否發生截斷,怎麼處理呢?
計算字數肯定不可行,因為涉及到不同手機,不同瀏覽器,不同字元,會有差異;
計算高度,比較展示全部和新增截斷時的高度值是否相等,相等時,說明不會截斷;不相等則說明發生截斷。
判斷文字是否截斷
我們不能直接使用該段落元素做判斷,使用者體驗很不好,我們可以新增一個輔助段落元素:
<p class="fake-content text-slice">
鄭成月的經歷就是一部中國社會歷史!很有價值的!不管是社會研究還是真心糾錯,都是非常好的案例。歷史就是用各種個人經歷寫成的,那樣就很有實在感。作家們沒有素材?都在書寫歌功頌德之文?想要把自己的作品流傳後世,這就是最好的素材
</p>複製程式碼
樣式如下:
.fake-content {
position: absolute;
z-index: -1; /* 隱藏 */
opacity: 0; /* 透明 */
pointer-events: none; /*元素不可互動/點選*/
}複製程式碼
然後比較此元素在設定截斷樣式和不設定截斷樣式時高度,相等即不會發生截斷,不相等即發生截斷:
// 文字是否發生截斷
function hasTextSliced($ele) {
var initHeight = $ele.height();
var height;
$ele.removeClass('text-slice'); // 刪除截斷樣式
height = $ele.height();
if (initHeight < height) {
// 發生截斷
return true;
}
return false;
}複製程式碼
如上,在刪除截斷樣式後,若高度變大,則說明發生文字截斷,否則不發生截斷。
CSS實現
CSS可以有兩種方式實現:
- :target偽類 實現
- :checked偽類 + ~(臨近兄弟節點選擇符)實現
:target偽類
我們知道HTML中,a連結可以設定錨點,點選後該錨點可以使用:target
偽類選擇獲取,於是可以為其設定文字不截斷樣式:
#content:target {
overflow: auto;
display: block;
}複製程式碼
其html結構如下:
<p class="content text-slice" id="content">
...
</p>
<p class="fake-content text-slice">
...
</p>
<a class="expand-more" href="#content">更多</a>複製程式碼
:checked偽類 + ~選擇符
此種方式原理是,選擇框可以使用CSS偽類:checked
獲取,然後通過~
選擇符給元素設定樣式不截斷文字:
#expand-check:checked ~ .content {
overflow: auto;
display: block;
}複製程式碼
html結構如:
<input type="checkbox" id="expand-check" style="display: none;pointer-events: none;">
<p class="content text-slice">
...
</p>
<p class="fake-content-2 text-slice">
...
</p>
<label class="expand-more" for="expand-check">更多</label>複製程式碼
如上,通過在文字前面新增一個隱藏的·<input type="checkbox">元素
,在更多按鈕中使用label的for屬性,通過設定<label class="expand-more" for="expand-check">
使其點選時可以改變前面新增的選擇框元素的checked狀態,從而實現切換效果。
總結
不同的方式都能實現效果,那什麼情況適合使用哪一種呢,現進行比較:
- 對比Js和CSS方式,Js實現可配置性,操作性強,而CSS實現有一定限制,無法在切換展示的同時進行其他Js處理;但是CSS實現更穩定,高效,程式碼,出錯性小,js錯誤不影響此功能,在內容展示型頁面適合使用。
- 對比:target偽類和:checked偽類,前者程式碼量少,不需要新增額外元素,但是我們知道錨點點選時,頁面是會滾動錨點元素到當前頁面頂部的,這不適合長頁面。
- :checked偽類方式需要為每一個需要切換展示的段落都新增額外輔助元素,因此不適於在長列表中使用,如評論列表,新聞簡介列表頁。
本篇中例項詳細程式碼參考https://github.com/codingplayboy/web_demo/tree/master/smallcase/expand_more
此篇關於文字截斷切換展示的總結,主要出於學習與實用的目的,若喜歡請點贊,文筆水平有限,望包含。