優雅的使用Js或CSS處理文字的截斷與展示

熊建剛發表於2017-04-25

之前遇見一個問題,就是處理文字截斷,然後可以手動切換文字是全展示和手動展示,因為這個問題比較常見,而且其實現方式有多種,於是決定總結一下,與讀者分享。

前言

首先,我們看這樣一個場景:

優雅的使用Js或CSS處理文字的截斷與展示
展開更多

其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

此篇關於文字截斷切換展示的總結,主要出於學習與實用的目的,若喜歡請點贊,文筆水平有限,望包含。

歡迎移步我的個人部落格

相關文章