「前端面試題系列3」僞類與僞元素的區別及實戰

圖片描述

前言

面試前端候選人的時候,我經常會問這樣一個有關CSS的問題:

你知道僞類與僞元素麼,它們的分別是什麼?
這時,能回答上來的很少。

換一種問法,你知道 :hover, :active, :focus, :visited麼?
這時,基本都能回答上來,這不就是a標籤的四種狀態麼。

嗯,ok。然後繼續問,那麼 ::before 和 ::after,聽說過麼?
這時,能聽到的回答是,嗯,我看到過,偶爾會用。

僞類與僞元素,都有一個“僞”字,那它們有什麼區別麼?
這時,迴應我的,是一片沉默。。。

從回答上來分析,雖然僞類和僞元素平時都有接觸,但在概念上,都比較模糊。今天,我們就來說說僞類與僞元素的區別,以及使用場景。僞類,不是隻有a標籤的四種狀態。僞元素,也不是隻有 ::before 與 ::after。更多的僞類與僞元素,詳見文末附錄。

概念上的區別

從概念上來區分,大致有以下幾點:

僞類,更多的定義的是狀態。常見的僞類有 :hover,:active,:focus,:visited,:link,:not,:first-child,:last-child等等。

僞元素,不存在於DOM樹中的虛擬元素,它們可以像正常的html元素一樣定義css,但無法使用JavaScript獲取。常見僞元素有 ::before,::after,::first-letter,::first-line等等。

CSS3明確規定了,僞類用一個冒號(:)來表示,而僞元素則用兩個冒號(::)來表示。但目前因爲兼容性的問題,它們的寫法可以是一致的,都用一個冒號(:)就可以了,所以非常容易混淆。

實戰場景——僞類

表單校驗

表單的校驗中,常會用到 :required:valid:invalid 這三個僞類。先來看看它們所代表的含義。

  • :required,指定具有 required屬性 的表單元素
  • :valid,指定一個 匹配指定要求 的表單元素
  • :invalid,指定一個 不匹配指定要求 的表單元素

看下面這個例子:

<p>input中類型爲email的校驗</p>

<p>符合email校驗規則</p>
<input type="email" required placeholder="請輸入" value="[email protected]" />
<br><br>

<p>不符合email校驗規則</p>
<input type="email" required placeholder="請輸入" value="lalala" />
<br><br>

<p>有required標識,但未填寫</p>
<input type="email" required placeholder="請輸入" value="" />
input {
    &:valid {
        border-color: green;
        box-shadow: inset 5px 0 0 green;
    }
    &:invalid {
        border-color: red;
        box-shadow: inset 5px 0 0 red;
    }
    &:required {
        border-color: red;
        box-shadow: inset 5px 0 0 red;
    }
}

效果如下:
圖片描述

摺疊面板

過去,要實現摺疊面板的顯示或隱藏,只能用JavaScript來搞定。但是現在,可以用僞類 :target 來實現。 :target 是文檔的內部鏈接,即 URL 後面跟有錨名稱 #,指向文檔內某個具體的元素。

看下面這個例子:

<div class="t-collapse">
    <!-- 在url最後添加 #modal1,使得target生效 —>
    <a class="collapse-target" href="#modal1">target 1</a>
    <div class="collapse-body" id="modal1">
        <!-- 將url的#modal1 變爲 #,使得target失效 —>
        <a class="collapse-close" href="#">target 1</a>
        <p>...</p>
    </div>
</div>
.t-collapse {
    >.collapse-body {
        display: none;
        &:target {
            display: block;
        }
    }
}

元素的index

當我們要指定一系列標籤中的某個元素時,並不需要用JavaScript獲取。可以用 :nth-child(n):nth-of-type(n) 來找到,並指定樣式。但它們有一些小區別,需要注意。

首先,它們的n可以是大於零的數字,或者類似2n+1的表達式,再或者是 even / odd。

另外,還有2個區別:

  • :nth-of-type(n) 除了關注n之外,還需要關注最前面的類型,也就是標籤。
  • :nth-child(n) 它關注的是:其父元素下的第n個孩子,與類型無關。

看下面這個例子,注意兩者的差異:

<h1>這是標題</h1>
<p>第一個段落。</p>
<p>第二個段落。</p>
<p>第三個段落。</p>
<p>第四個段落。</p>
<p>第五個段落。</p>

圖片描述

實戰場景——僞元素

antd的彩蛋事件

還記得2018年聖誕節的“彩蛋事件”,在整個前端圈,轟動一時。因爲按鈕上的一朵雲,導致不少前端er提前回家過年了。當時,彩蛋事件出現的第一時間,就嚇得我趕快打開工程看了一眼,果然也中招了。爲了保住飯碗,得趕緊把雲朵去掉。

查看了生成的html,發現原來是 button 下藏了一個 ::before。所以,趕緊把樣式覆蓋掉,兼容代碼如下:

.ant-btn {
    &::before {
        display: none !important;
    }
}

美化選中的文本

在網頁中,默認的劃詞效果是,原字色保持不變,劃過時的背景變爲藍底色。其實,這是可以用 ::selection 來進行美化的。看下面這個例子:

<p>Custom text selection color</p>
::selection {
    color: red;
    background-color: yellow;
}

效果如下:
圖片描述

劃過的部分美化爲:紅色的字體,並且底色變爲了黃色。

總結

CSS也可以實現動態的交互,並非只有JavaScript才能實現。

書寫的時候,要尊重規範。寫僞類的時候用 :,而寫僞元素的時候用 ::

兼容性的問題,交給postcss去做。本文並未涉及兼容性的寫法,包括前綴問題,可以交給autoprefixer去做。

附錄

CSS3中的僞類

:root 選擇文檔的根元素,等同於 html 元素
:empty 選擇沒有子元素的元素
:target 選取當前活動的目標元素
:not(selector) 選擇除 selector 元素意外的元素
:enabled 選擇可用的表單元素
:disabled 選擇禁用的表單元素
:checked 選擇被選中的表單元素
:nth-child(n) 匹配父元素下指定子元素,在所有子元素中排序第n
:nth-last-child(n) 匹配父元素下指定子元素,在所有子元素中排序第n,從後向前數
:nth-child(odd) 、 :nth-child(even) 、 :nth-child(3n+1)
:first-child 、 :last-child 、 :only-child
:nth-of-type(n) 匹配父元素下指定子元素,在同類子元素中排序第n
:nth-last-of-type(n) 匹配父元素下指定子元素,在同類子元素中排序第n,從後向前數
:nth-of-type(odd) 、 :nth-of-type(even) 、 :nth-of-type(3n+1)
:first-of-type 、 :last-of-type 、 :only-of-type

CSS3中的僞元素

::after 已選中元素的最後一個子元素
::before 已選中元素的第一個子元素
::first-letter 選中某個款級元素的第一行的第一個字母
::first-line 匹配某個塊級元素的第一行
::selection 匹配用戶劃詞時的高亮部分

PS:歡迎關注我的公衆號 “超哥前端小棧”,交流更多的想法與技術。
1334261100-5c1de2b334a9e_articlex

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章