2012-06-27 78 views
6

考慮到CSS處理細節,最值得注意的是RTL matchingselector efficiency,應該如何純粹從渲染引擎性能的角度編寫選擇器?基於計算複雜度選擇高效選擇器

這應該覆蓋一般方面,包括使用或避免僞類,僞元素和關係選擇器。

+1

好問題,但永遠記住:表現不是一切,除非它是唯一需要擔心的事情。如果您確信您絕對需要儘可能節省成本並且您的設計能夠滿足需求,那麼您只需擔心性能問題。 – BoltClock

+2

如果您想...剖析您的CSS選擇器,Chrome開發人員工具中的「CSS選擇器分析器」非常有用。 – thirtydot

回答

6

在運行時,HTML文檔被解析爲一個DOM樹,其中包含N元素,平均深度爲D。在應用的樣式表中總共也有S CSS規則。

  1. 元素的樣式應用於單獨意味着N和總體複雜性之間有直接的關係。值得注意的是,這可以通過瀏覽器邏輯,如參考緩存和來自相同元素的回收樣式略微抵消。例如,下面的列表項將應用相同的CSS屬性(假設如:nth-child沒有適用的僞類):

    <ul class="sample"> 
        <li>one</li> 
        <li>two</li> 
        <li>three</li> 
    </ul> 
    
  2. 選擇器匹配從右到左爲單獨的規則資格 - 即,如果最右邊的鍵不匹配特定的元素,不需要進一步處理選擇器並將其丟棄。這意味着最右邊的鍵應儘可能少地匹配。下面,p描述符將匹配更多的元素,包括外目標容器的(其中,當然,不會有應用該規則,但仍然會導致資格的更反覆檢查特定的選擇)段落

    .custom-container p {} 
    .container .custom-paragraph {} 
    
  3. 關係選擇器:後代選擇器最多需要D元素才能在上迭代。例如,成功匹配.container .content可能只需要一個步驟,如果元素處於父子關係中,但DOM樹將需要一直遍歷到html,然後才能確認元素不匹配,並且規則將被安全丟棄。這也適用於鏈接的後代選擇器,並帶有一些限制。

    在另一方面,一個>子選擇,一個+相鄰選擇或:first-child仍然需要額外的元件進行評價,但是隻具有一個的一個隱含的深度,絕不會需要進一步的樹遍歷。

  4. behavior definition的僞元素,如:before:after意味着它們不是RTL範例的一部分。假設的邏輯是,除非規則指示要在元素的內容之前或之後插入它(這反過來需要額外的DOM操作,但不需要與選擇器本身相匹配的額外計算),否則本身不存在僞元素。

  5. 我找不到僞類的任何信息,如:nth-child():disabled。驗證元素狀態將需要額外的計算,但是從規則解析角度來看,它們只對從RTL處理中排除它們有意義。

鑑於這些關係,計算複雜度O(N*D*S)應主要通過最小化CSS選擇的深度和解決上述點2被降低。與最小化CSS規則或HTML元素數量相比,這將導致量化更強的改進^

淺,最好是一級特定選擇器處理得更快。這被認爲是一個全新的水平由谷歌(編程,不要用手!),比如很少有一個三鍵選擇,並在搜索結果中大部分的規則看起來像

#gb {} 
#gbz, #gbg {} 
#gbz {} 
#gbg {} 
#gbs {} 
.gbto #gbs {} 
#gbx3, #gbx4 {} 
#gbx3 {} 
#gbx4 {} 
/*...*/ 

^- 雖然這是從渲染引擎性能的角度來看真正的,總有一些額外的因素,如通信開銷和DOM解析等

來源:12345

+1

在選擇器中,所有僞元素(不僅僅是':: before'和':: after')都遵循相同的規則,它們只能應用於選擇器的主體,並且僅在選擇器匹配完成後才被評估 - http://www.w3.org/TR/selectors/#pseudo-elements從CSS1到CSS3,這總是關鍵選擇器;然而在CSS4中這可能會改變。 – BoltClock

+1

RTL解析是一個實現細節,它可能因引擎而異,但是從關鍵選擇器開始並向後倒退的一般概念在供應商之間達成一致。首先評估每個化合物選擇器中哪些簡單的選擇器似乎只是源代碼可以回答的東西...更多關於[這裏](http://stackoverflow.com/questions/10106345/css-selector-engine-clarification/ 10108700#10108700)。 – BoltClock

+0

@BoltClock:好點;我願意推測,CSS4父選擇器將實際上是一個帶有* has-children *條件的僞類 - 否則可能會有很多冗餘匹配週期。至於特定於代碼的插件,他們可能會更好地堅持建議的行爲 - 一個值得關注的例子就是IE7緩存':first-child'引用 –