css偽元素:before和:after用法詳解


css的偽元素,之所以被稱為偽元素,是因為他們不是真正的頁面元素,html沒有對應的元素,但是其所有用法和表現行為與真正的頁面元素一樣,可以對其使用諸如頁面元素一樣的css樣式,表面上看上去貌似是頁面的某些元素來展現,實際上是css樣式展現的行為,因此被稱為偽元素。如下圖,是偽元素在html代碼機構中的展現,可以看出無法偽元素的結構無法審查。

css有一系列的偽元素,如:before,:after,:first-line,:first-letter等,本文就詳述一下:before和:after元素的使用

####一、偽元素:before和:after用法

這個兩個偽元素在真正頁面元素內部之前之后添加新內容(當然了,可以對偽元素應用定位可以置於任何位置)。可以用以下例子來說明:

    <p>wonyun!</p>
    <style>
        p:before{content: "hello "}
        p:after{content: "you are handsome!"}
    </style>

上面例子從技術角度看,等價於下面的html結構:

    <p>
        <span>hello </span>
        wonyun!
        <span> you are handsome!</span>
    </p>

由此可知:偽元素:before和:after添加的內容默認是inline元素;這個兩個偽元素的content屬性,表示偽元素的內容,設置:before和:after時必須設置其content屬性,否則偽元素就不起作用。那么問題來了,content屬性的值可以有哪些內容呢,具體有以下幾種情況:

  • 字符串,字符串作為偽元素的內容添加到主元素中

    注意:字符串中若有html字符串,添加到主元素后不會進行html轉義,也不會轉化為真正的html內容顯示,而是會原樣輸出

  • attr(attr_name), 偽元素的內容跟主元素的某個屬性值進行關聯,及其內容為主元素的某指定屬性的值

    好處:可以通過js動態改變主元素的指定屬性值,這時偽元素的內容也會跟着改變,可以實現某些特殊效果,如圖片加載失敗用一段文字替換。

  • url()/uri(), 引用外部資源,例如圖片;

  • counter(), 調用計數器,可以不使用列表元素實現序號問題。


####二、:before和:after特點

上面說了,偽元素是通過樣式來達到元素效果的,也就是說偽元素不占用dom元素節點,引用:before,:after偽元素妙用里面總結的,:before和:after偽元素的主要特點如下:

  • 偽元素不屬於文檔,所以js無法操作它

  • 偽元素屬於主元素的一部分,因此點擊偽元素觸發的是主元素的click事件

  • 原文說塊級元素才能有:before, :after,其實是不妥的,大部分行級元素也可以設置偽元素,但是像img可替換元素,因為其外觀和尺寸有外部資源決定,那么如果外部資源正確加載,就會替換掉其內部內容,這時偽元素也會被替換掉,但是當外部資源加載失敗時,設置的偽元素是可以起作用的。

基於偽元素的特點可以知道其優缺點,也引用別人文章的話:

  • 優點

    • 減少dom節點數
    • 讓css幫助解決部分js問題,讓問題變得簡單
  • 缺點

    • 不利於SEO
    • 無法審查元素,不利於調試

####三、:before和:after常見使用場景

  1. 清除浮動
清除浮動是前端最常見的問題,有一種做法是使用一個空的頁面元素如div來清除浮動,但是這種做法增加毫無語義的頁面元素,而且占用dom節點。更可取的做法是利用偽元素來清除浮動:
            <div class="l-form-row">
                <div class="l-form-label"></div>
                ....
            </div>
            <style>
                .l-form-row:after {
                    clear: both;
                    content: "\0020";
                    display: block;
                    height: 0;
                    overflow: hidden
                }
            </style>

這樣,class=l-form-row的元素內部任何浮動都能清除掉,不用額外添加無意義的元素。

  1. 利用attr()來實現某些動態功能

在頁面中常見這種問題,頁面上加載的圖片在無法加載時會顯示一個破損圖片,直接影響頁面的美觀;

那么可以通過偽元素配合樣式能夠讓未加載的圖片看起來真的像破裂的效果,如下圖所示:

<img>是一個替換元素,其外觀和尺寸是由外部資源來決定的,當外部圖片資源加載失敗時其會顯示破裂圖片和alt文字,尺寸僅由其自身內容決定。這時<img>元素可以使用偽元素:before:after,因為其元素內容沒有被替換;利用attr()來獲取圖片alt屬性值作為偽元素:aftercontent內容來替換img的內容,並運用適當的樣式從而完成:圖片加載成功時顯示正常的圖片,加載失敗時顯示圖片破裂效果的樣式,具體代碼參考:

        img{
            min-height: 50px;
           position: relative;
        }
        img:before: {
             content: " ";
             display: block;
            position: absolute;
            top: -10px;
            left: 0;
            height: calc(100% + 10px);
            width: 100%;
            backgound-color: rgb(230, 230,230);
            border: 2px dotted rgb(200,200,200);
            border-radius: 5px;
        }
        img: {
            content: '\f127" " Broken Image of " attr(alt);
            display: block;
            font-size: 16px;
            font-style: normal;
            font-family: FontAwesome;
            color: rgb(100,100,100)
            position: absolute;
            top: 5px;
            left: 0;
            width: 100%;
            text-align: center;
        }
  1. 與counter()結合實現序號問題,而不用使用列表元素。具體還要結合css的 counter-increment 和 counter-reset 屬性的用法 。

代碼如下:

        <h2></h2>
        <h2></h2>
        <style>
            body {counter-reset:section;}
            h2:before { 
                counter-increment: section; 
                content: "Chapter"  counter(section) ".";
            }
        </style>

結果如下:

  1. 特效使用

利用這兩個偽元素,可以實現各種效果,如放大鏡、叉叉、箭頭、三角符等,也可輕易實現如下效果 代碼實現如下:

        a {
	    position: relative;
	    display: inline-block;
	    outline: none;
	    text-decoration: none;
	    color: #000;
	    font-size: 32px;
	    padding: 5px 10px;
        }

        a:hover::before, a:hover::after { position: absolute; }
        a:hover::before { content: "\5B"; left: -20px; }
        a:hover::after { content: "\5D"; right:  -20px; }

代碼實現如下:

        table{overflow: hidden;}
        td, th{
            padding: 10px;
            position: relative;
            outline: 0;
        }
        td:hover::after,
        th:hover::after { 
              content: '';  
              background-color: lightblue;
              position: absolute;  
              left: 0;
              height: 10000px;
              top: -5000px;
              width: 100%;
              z-index: -1;
        }

        td:hover::before {
              background-color: lightblue;
              content: '';  
              height: 100%;
              top: 0;
              left: -5000px;
              position: absolute;  
              width: 10000px;
              z-index: -1;
        }
    

具體代碼:

        .empty__bg {
                display: inline-block;
                width: 95px;
                height: 92px;
                background: url(http://7tszky.com1.z0.glb.clouddn.com/FvD_sYY4Fmp_yKS0E07H-5jhuKTB) no-repeat;
                background-size: 95px 92px;
                position: relative;
                margin-bottom: 16px;/*注意這里需要留好位置放置after元素(它是absolute進去的)*/
            }
            .empty__bg:after {
                content: "暫無學習計划";
                display: block;
                font-size: 14px;
                line-height: 24px;
                text-align: center;
                width: 100%;
                color: #909090;
                position: absolute;
                top: 100%;
                left: 0;
            }
        }

上述可以實現擴大可點擊區域,這對應手機用戶來說更加友好一些,否則用戶點擊不會觸發相應的事件;具體代碼實現如下:

        .play-cover {position: relative}
        .play-cover:before{
            content: "";
            display: block;
            position: absolute;
            width: 0;
            height: 0;
            border-left: 8px solid white;
            border-top: 5px solid transparent;
            border-bottom: 5px solid transparent;
            margin-left: 9px;
            margin-bottom: 7px;
            z-index: 5;
        }
        .play-cover:after{
            content: '';
            display: block;
            position: absolute;
            width: 20px;
            height: 20px;
            border: 2px solid white;
            background: rgba(0, 0, 0, .6);
            border-radius: 12px;
            background-clip: padding-box;
        }

CSS美化radio和checkbox的樣式magic-check,就是利用偽元素:before和:after來實現的; 具體是為每個真正的表單元素radio和checkbox搭配一個label,然后隱藏真正的radio和checkbox,label元素單擊的時候隱藏的radio或者checkbox實際上是處於checked狀態,這跟label的具體用法有關;利用label的偽元素:before和:after來實現美化radio和checkbox。

下面是checkbox的美化的css代碼:

        .magic-checkbox {
              position: absolute;
              display: none;  //先隱藏真正的checkboxbox
         }
         .magic-checkbox + label {//為與checkbox搭配的label使用樣式
              position: relative; //相對定位,方便其內容的偽元素進行定位
              display: block; //塊元素
              padding-left: 30px;
              cursor: pointer;
              vertical-align: middle; 
         }
        .magic-checkbox + label:before { //label添加:before偽元素,用於生成一個帶邊界的正方形,模擬復選框的輪廓
                position: absolute;
                top: 0;
                left: 0;
                display: inline-block;
                width: 20px;
                height: 20px;
                content: '';
                border: 1px solid #c0c0c0; 
                border-radius: 3px; 
            }
            //為checkbox添加:after偽元素,作用是生成一個√圖形,模擬checkbox選中狀態,未選中狀態下會被隱藏
            .magic-checkbox + label:after {
                  top: 2px;
                  left: 7px;
                  box-sizing: border-box;
                  width: 6px;  //實現√圖形很簡單:設置一個長方形,去掉其上邊界和左邊界,剩下的2個邊界旋轉45度就得到√形狀
                  height: 12px;
                  transform: rotate(45deg);
                  border-width: 2px;
                  border-style: solid;
                  border-color: #fff;
                  border-top: 0;
                  border-left: 0;
                  position: absolute;
                  display: none; //√形狀先隱藏
                  content: '';
              }
            //單擊label,隱藏的checkbox為checked狀態,這時設置checked狀態下搭配label的:before偽元素背景和邊界顏色
             .magic-checkbox:checked + label:before {
                    animation-name: none; 
                    border: #3e97eb;
                    background: #3e97eb; 
                }
            //checked狀態的checkbox搭配的label偽元素:after此時設置顯示,那么√就顯示出來了
             .magic-checkbox:checked + label:after {
                  display: block; 
             }

利用:before和:after能輕易實現美化的radio和checkbox


參考文檔

  1. :before,:after偽元素妙用
  2. 前端開發中的一些黑魔法Pt1
  3. 你所不知的 CSS ::before 和 ::after 偽元素用法
  4. 純CSS制作各種圖形(多圖預警)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM