溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

CSS元素選擇器是如何運作的

發(fā)布時間:2021-10-26 09:28:18 來源:億速云 閱讀:159 作者:iii 欄目:web開發(fā)

本篇內(nèi)容介紹了“CSS元素選擇器是如何運作的”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

在前端工程師的日常工作中,使用 CSS 元素選擇器是稀松平常的事;無論你是編寫一般的 CSS 還是需要經(jīng)過編譯的  SASS,SCSS,LESS等,最終都被編譯成一行一行的 CSS 樣式屬性,最終交給瀏覽器解析并套用。但是你想過沒有這是如何實現(xiàn)的呢?

CSS元素選擇器是如何運作的

瀏覽器渲染

我們先看一下瀏覽器的渲染步驟:

CSS元素選擇器是如何運作的

CSS 在被瀏覽器加載后,會被解析成 CSSOM 樹,并嘗試與 Dom 疊加成渲染樹,隨后進(jìn)行計算位置、渲染等步驟。這樣看來,CSS  屬性套用的關(guān)鍵就在于如何從 CSS 轉(zhuǎn)化成 CSSOM 樹,以及怎么把 CSSOM 套用到 DOM 上去。

CSSOM樹

當(dāng)我們寫下一組 CSS 樣式時,例如:

#id .class h5 + p {    ... }

瀏覽器在解析它時,你可能會認(rèn)為 CSS 會按照由左到右的依序找出#id>.class>h5>p,最后套用,但實際上瀏覽器解析 CSS  的順序是由右到左的 p>h5>.class>#id。

很違背直覺對吧?但如果考慮到性能問題,從右到左的解析會比從左到右強(qiáng)很多。

假設(shè)這有這樣的 HTML:

<div id="div1">     <div class="a">         <div class="b">             ...         </div>         <div class="c">             <div class="d">                 ...             </div>             <div class="e">                 ...             </div>         </div>     </div>     <div class="f">         <div class="c">             <div class="d">                 ...             </div>         </div>     </div> </div>

以及這邊五條 CSS 樣式規(guī)則:

#div1 .c .d {} .f .c .d {} .a .c .e {} #div1 .f {} .c .d {}

讓我們模擬一下,如果把 CSS 從左到右解析,將會生成類似這樣的 CSSOM 樹:

CSS元素選擇器是如何運作的

通過<div class =“ d”>中的 .d 來思考,這樣的 CSSOM 樹在套用樣式時,必須對所有的樣式規(guī)則進(jìn)行檢查,以確認(rèn)樣式規(guī)則是否會影響到  .d,到最后才能確定可能會影響到 .d 的樣式規(guī)則有這三條:

  • #div1 .c .d

  • .f .c .d

  • .c .d

以此類推,每個 DOM  樹上的元素,都必須便利所有的樣式規(guī)則,才可以取得個別的樣式,這樣會造成大量冗余的計算,進(jìn)而嚴(yán)重影響性能。

反過來,如果將前面的 CSS 由右到左進(jìn)行解析,CSSOM 樹則可能會如下:

CSS元素選擇器是如何運作的

和前面的例子一樣,從<div class =“ d”>中 .d 的角度來看,由于會被樣式規(guī)則影響到的目標(biāo)元素,已經(jīng)全都集中在第一層了,所以就不用再去便利整個 CSSOM  樹了,甚至只需要檢查 .d 以下的子屬性變量是否符合實際 DOM 結(jié)構(gòu),再將所有符合的樣式規(guī)則重新取回,便能完成 .d 對元素的樣式規(guī)則套用。

從右到左的解析順序能夠?qū)⑺泄蚕淼囊?guī)則路徑收攏在一起,當(dāng)瀏覽器進(jìn)行屬性比對時,就不用再便利整個 CSSOM 樹,大大的減少了無效的比對計算。

也可以換個方式思考:在 HTML 的結(jié)構(gòu)中,一個元素可以有無數(shù)個子元素,但只能有一個父元素,由子找父(由下往上)搜尋絕對是比較快的。

1. 套用樣式

將 CSSOM 樹解析出來之后就能夠和 DOM 結(jié)合了嗎?如果真的有這么簡單就太好了。

除了開發(fā)者定義好的 CSS 檔外,還有幾個地方可能會定義樣式規(guī)則,影響畫面的渲染:

  • HTML 的 inline style 設(shè)置

  • 瀏覽器預(yù)設(shè)值(就是 CSS reset/normalize 要覆蓋掉的東西)

  • 瀏覽器的使用者偏好設(shè)定

瀏覽器負(fù)責(zé)處理 CSS 的部分,會吧前面所有的東西以及 CSS 文件定義的樣式規(guī)則分別整理成單獨的樣式規(guī)則組(CSS  規(guī)則集),內(nèi)容記載了樣式規(guī)則、目標(biāo)屬性等信息。

2. 目標(biāo)屬性

為了提升后面的計算效率,瀏覽器的 CSS 處理內(nèi)核會按照樣式規(guī)則組中個別規(guī)則的目標(biāo)屬性將其分組存放;一共分為以下四組

  • idRules

  • classRules

  • tagNameRules

  • universalRules

這樣在取用時,可以依據(jù)目標(biāo)元素是否存在這個屬性,快速篩出可能會套用的樣式。

套用規(guī)則

最后是套用規(guī)則。瀏覽器會遵循以下順序和樣式規(guī)則權(quán)重套用所有的樣式規(guī)則:

  • 瀏覽器的預(yù)設(shè)值

  • 瀏覽器的使用者偏好設(shè)定

  • 開發(fā)者定義的 CSS

  • inline style

  • 加上 !important 的樣式屬性

你可能會好奇:為什么 inline style 和開發(fā)者定義的 CSS 會被另外處理?

我們可以回顧一下瀏覽器渲染的步驟,由于 inline style 存在于 DOM 元素中,只能在 CSS 套用到 DOM  上時才會接觸到,事前無法將兩者結(jié)合。

CSS 效率

實際上瀏覽器在這里已經(jīng)完成了優(yōu)化機(jī)制;瀏覽器會自動將狀態(tài)一致的元素做樣式快照。狀態(tài)一致就是要滿足以下幾個條件:

  • 沒有設(shè)定 ID

  • tag 及 class 必須完全一致

  • 沒有設(shè)定 style 屬性

  • 樣式規(guī)則中不能使用各種同級選擇器(例如:?,+,:first-child 等)

由于上面的條件,以及前面討論到的 CSS 運算過程,編寫 CSS 時也有幾個地方可以稍微留心一下:

  • 由于樣式規(guī)則的目標(biāo)屬性會分組存放,id 選擇器效率非常高,所以是不能與其他條件混用的。

  • 不要寫過深的 CSS 樣式規(guī)則

  • 能不用 inline style 就不要用,除了難以維護(hù)外,由于是存在于 DOM 樹上,無法預(yù)先與其他樣式合并計算,所以效率也會大打折扣

如果能夠注意到這類典型的小細(xì)節(jié),CSS 效率自然也可以大幅提升。

“CSS元素選擇器是如何運作的”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

css
AI