CSS選取器的權重詳解

來源:互聯網
上載者:User
文章目錄
  • 相關參考連結:

在我們開始之前,先搞明白幾個概念吧。下面是一段CSS代碼:

      a {        border-bottom: 0px;        color: #5DB0E6;      }      a:focus {        outline: 1px dotted #eee;      }      a:active {        outline: 0px;      }      a:hover {        color: #7bc4f4;      }      body#jq-interior {        background-image: url(http://static.jquery.com/files/rocker/images/bg-interior-tile-drk.jpg);      }

上面這個樣式表是由一個個樣式規則群組成,而每一個樣式規則又可以分為兩部分:選擇符與聲明。選擇符就相當於jQuery的選取器,能針對特定元素進行設定。CSS有名叫層疊樣式表,基本上被選中的元素的子項目能繼承它的樣式,但其子項目如果設定了樣式,也能覆寫它,就像板頁岩這樣累在一起。隨著表格版面配置這樣落後的布局方式的式微,CSS越來越受到人們的重視。但IE6對CSS的支援不足與各種層不窮的bug,或者是某些大型網站對CSS的不合理使用,CSS的體積膨脹起來了。維護它們可是一件麻煩事,如何讓元素顯示出想要的樣式,我們就必須對權重這個概念有所瞭解。權重你可以說是針對樣式規則的,也可以說針對選擇符。之所以這樣說,因為有一個重要的標識符! important可以放到樣式聲明的最後,用來無視本文重點說的權重等級。我覺得最好還是不要用這東西,首先IE6對它支援不好,要支援它需要把一個樣式規則分開寫,另,用多了會嚴重擾亂CSS的權重等級。

有關CSS權重等級的介紹最早見於W3C這篇文章,聽說IE5是最早支援CSS的,不知哪個早一點呢?很明顯IE是沒有完全照足它來實現。在《Calculating a selector's specificity》一章,它粗略地用a、b、c、d來對樣式規則進行評估,給出每一個的得分(1 或 0),但沒有給出最終值的計算方式。

  • a:如果這個元素應用了行內樣式,它才分配此值為1。怎麼是行內樣式呢?就是標籤內使用style="...."的方式來設定樣式,我覺得這是很愚蠢的行為,徒然增加頁面的體積,也非常不好維護,和使用那些純表示樣式的元素差不多,如big、small、b、u、strike 等等。這樣做法,我個人覺得,瀏覽器其實是為它分配了一個特別的ID(實質上IE也是為頁面上每個元素分配了一個uniqueId),然後把它置於樣式表的最下方,於是就沒有其他樣式能覆蓋它了。
  • b:指一個樣式規則的選擇符存在id選取器。比如上面的body#jq-interior ,不過這樣有點累贅了。我看了許多CSS選取器的實現,還有我在做選取器的經驗,body完全沒有必要。一個選擇符就相當於一個選取器群組,它由各種各樣的選取器組成。選取器得到一個符合CSS選擇符結構的字串,如果它足夠聰明的話,會先對字串進行trim操作,然後進行掃描,看有沒有id選取器,有的話會砍掉前面的部分,然後再用正則對其進行肢解……換言之,id選取器具有強烈的排它性,只有並聯選取器可以容忍它。
  • c:指一個樣式規則的選擇符是否存在類別選取器與偽類別選取器(:hover,:link,:active,:target)。這些基本上CSS2.1的東西,CSS3增加的基本是結構偽類還有一個selection虛擬元素,沒有破壞這個評分體系。
  • d:這個權重最低了,指選擇符裡存在標籤選取器,與虛擬元素。何為虛擬元素呢?前面有::的東西就是虛擬元素了。注意,早期的虛擬元素也和偽類一樣,只有一個冒號。這可能是後來w3c心血來潮,把它們分離出來(css3規範),造成今天的樣子。

雖然到目前為止,我們已經知道a的權重肯定大於b,而b大於c,d最小,但這實在不好計算,對於接著下來的樣本也不好解說。於是我引進外國另一個補充方案,它出於這篇名叫《CSS: Specificity Wars》的有才文章。。它把abcd當成算術上的個、十、百、千這樣的計數單位,各自相乘最後一加,優先順序就一目瞭然啦。我們甚至可以將它們轉化為以下一個直觀的圖示。

好了,我們開始分析一下w3c的樣本,看它能給我們什麼多餘的資訊。

  /*by 司徒正美 All rights reserve*/  *             {}  /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */  /* 萬用字元選取器權重為0,在IE中,它無法區分元素節點與注釋節點 */  li            {}  /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */  /* 標籤選取器為1 */  li:first-line {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */  /* 標籤選取器與虛擬元素為1 */  ul li         {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */  /*這裡存在後代選取器的概念,但計算權重時像它這樣的關係選取器會被進一步肢解,當成兩個標籤選取器了。*/  ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */  /* 無視後代選取器與相鄰選取器,只看它裡面的選取器的成分 */  h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */  /* 這個相鄰選取器由標籤選取器與屬性選取器組成,屬性選取器為10 */  ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */  /*無視後代選取器,3個標籤與1個類別選取器,類(className)在DOM中的位置比較顯赫,  擁有專門的getElementByClassName,等級為c,合計得分13 */  li.red.level  {}  /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */  /*兩個類別選取器與一個標籤選取器,合計得分21 */  #x34y         {}  /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */  /*getElementById,在頁面上獲得元素最快的方式,權重為b,得分100 */  style=""          /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */  /*行內樣式,得分1000,會覆蓋內部樣式或外部樣式的設定*/

最後總結一下,十大選取器與虛擬元素的權重情況:

選取器 運算式或樣本 說明 權重
ID選取器 #aaa 100
類別選取器 .aaa 10
標籤選取器 h1 元素的tagName 1
屬性選取器 [title] 詳見這裡 10
相鄰選取器 selecter + selecter 拆分為兩個選取器再計算
兄長選取器 selecter ~ selecter 拆分為兩個選取器再計算
親子選取器 selecter > selecter 拆分為兩個選取器再計算
後代選取器 selecter selecter 拆分為兩個選取器再計算
萬用字元選取器 * 0
各種偽類別選取器 如:link, :visited, :hover, :active, :target, :root, :not等 10
各種虛擬元素 如::first-letter,::first-line,::after,::before,::selection 1
相關參考連結:
  • specificity at westciv
  • specificty for star wars fans
  • specificity at snook.ca
  • eric meyer on specificity
  • CSS Structure and Rules
相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.