天天看點

僞元素:before和:after用法

css的僞元素之是以稱之為僞元素,是因為他們不是真正的頁面元素,html沒有對應的元素,但是其所有用法和表現行為與真正的頁面元素一樣,可以對其使用諸如頁面元素一樣的css樣式,表面上看上去貌似是頁面的某些元素來展現,實際上是css樣式展現的行為,是以被稱為僞元素。

看例子:

<div class="box">xiaobai</div>
 
樣式:
.box:before{content:"hello"}
.box:after{content:"how are you?"}




           

運作結果就會變成:hello xiaobai  how are you?

由此可知:僞元素:before和:after添加的内容預設是inline元素;這個兩個僞元素的content屬性,表示僞元素的内容,設定:before和:after時必須設定其content屬性,否則僞元素就不起作用。那麼問題來了,content屬性的值可以有哪些内容呢

具體有以下幾種情況:

  • 字元串,字元串作為僞元素的内容添加到主元素中:
a:after{content:"→"}
           

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

  • attr(attr_name), 僞元素的内容跟主元素的某個屬性值進行關聯,及其内容為主元素的某指定屬性的值
a:after { content:"(" attr(href) ")"; }
           

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

  • url()/uri(),引用外部資源,例如圖檔;
h1::before { content: url(logo.png); }
           
  • counter(), 調用計數器,可以不使用清單元素實作序号問題。
h2:before { counter-increment: chapter; content: "Chapter " counter(chapter) ". " }
           

對僞元素的描述

僞元素不屬于文檔,是以js無法操作它

僞元素屬于主元素的一部分,是以點選僞元素觸發的是主元素的click事件

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

基于僞元素的特點可以知道其優缺點,也引用别人文章的話:

優點

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

缺點

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

:before和:after常見使用場景

1.清除浮動

.box:after{
    content:"";
    display:block;
    clear:both;
    height:0;
    overflow:hidden;
    visibility:hidden;
}
.box{
   zoom:1;
}
           

2.在頁面中常見這種問題,頁面上加載的圖檔在無法加載時會顯示一個破損圖檔,直接影響頁面的美觀,可以通過僞元素配合樣式能夠讓未加載的圖檔看起來真的像破裂的效果

<img>是一個替換元素,其外觀和尺寸是由外部資源來決定的,當外部圖檔資源加載失敗時其會顯示破裂圖檔和alt文字,尺寸僅由其自身内容決定。這時<img>元素可以使用僞元素:before和:after,因為其元素内容沒有被替換;利用attr()來擷取圖檔alt屬性值作為僞元素:after的content内容來替換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;
        }
           

3. 與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>
           

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

.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;
        }
           

5.方框内容追加三角形

p::before{
     display:inline-block;
     border:5px solid transparent;
     border-right-color:green;
     content:"";
     porsition:relative;
     left:-10px;
           

6.做機關、标簽、表單必填标準

表單輸入框的必填标記(往往是紅色的“*”字元),不應該放到文檔當中,使用::before可以很優雅地解決這個問題(其實就是字元圖示的進一步應用)

<label calss="name">
    "姓名"
    <input />
</label>


樣式:
.name::before{
    content:“*”;
    color:red;
    diplay:inline-block;
    width:0;
    position:relative;
    left:-5px;
}