***CSS魔法堂:選擇器及其優先順序

suboysugar發表於2015-12-11

一、前言                               

首先看看一道阿里這期網申的題目吧!

1.找出下面優先順序相同的選擇器

  A. img.thumb:after  B.[data-job=”frontend”]::first-letter

  C. #main::before     D. [type=”checkbox”]:checked  E. ul#shop-list

 

二、回顧選擇器型別                               

 html片段

複製程式碼
<body>
  <div id="content">
    <div>Hello world</div>
    <div class="block-end">EOF</div>
  </div>
</body>
複製程式碼

 基本選擇器


 

  1. 元素(型別)選擇器

div{
  color: red;
}

  2. 類選擇器

.block-end{
  color: #000;
}

  3. ID選擇器

#content{
  color: blue;  
}

  4. 通用元素選擇器,匹配任何元素(IE5.5不支援)

*{
  width: 1000px;
}

 

組合選擇器


 

1. 群組選擇器

/** 格式
 * 選擇器A, 選擇器B{樣式規則}
 */
div, body{
  width: 1200px;
}

對N個選擇器獲取的dom元素應用同一個樣式,減少重複程式碼。

2. 後代選擇器(派生選擇器)

/** 格式
 * 父選擇器 後代選擇器{樣式規則}
 */
body div{
  color: #888;
}

body下的所有div元素均應用上述樣式。

3. 子元素選擇器(IE5.5~IE6不支援)

/** 格式
 * 父選擇器 > 子元素選擇器{樣式規則}
 */
body > div{
  color: #111;
}

僅body的div孩子元素才應用上述樣式。

4. 毗鄰弟弟元素選擇器(原名相鄰兄弟元素選擇器)(IE5.5~IE6不支援)

/** 格式
 * 選擇器A + 選擇器B{樣式規則}
 */
#content + div{
  color: #111;
}

僅div#content後緊跟著的同級div應用上述樣式,若如 <div id=”content”></div><br/><div id=”block-end”>EOF</div> ,由於div#block-end不是緊跟在div#content後,因此不會應用上述樣式。

5. 弟弟元素選擇器(原名為兄弟選擇器)(IE5.5~IE6不支援)

/** 格式
 * 選擇器A ~ 選擇器B{樣式規則}
 */
#content ~ div{
  color: #222;
}

僅div#content後的同級div都會應用上述樣式,如 <div id=”content”></div><br/><div id=”block-end”>EOF</div>  ,div#block-end都會應用上述樣式。

 

屬性選擇器


 

1. 基礎選擇器[attr](如: div[id] )(IE5.5~IE6不支援

  匹配所有具有該屬性,且符合基礎選擇器條件的元素。

2. 基礎選擇器[attr=value](如 div[id=content] )IE5.5~IE6不支援

  匹配所有attr的屬性值等於value,且符合基礎選擇器條件的元素。

3基礎選擇器[attr~=value](如 div[val~=content] )IE5.5~IE6不支援

  匹配如<div val=”content dir”></div>的元素,就是匹配屬性值具有多個空格分隔的值,其中一個值等於value的元素。

4. 基礎選擇器[attr|=value](如 div[lang|=en] )IE5.5~IE6不支援

 匹配如<div lang=”en-us”></div>的元素,就是匹配屬性值以value或value-為開頭的元素。

5. 基礎選擇器[attr^=value](如 div[id^=cont] )IE5.5~IE6不支援

 匹配如<div id=”content”></div>或<div id=”contdummy”></div>的元素,就是匹配屬性值以value開頭的元素。

6. 基礎選擇器[attr$=value](如 div[id$=tent] )IE5.5~IE6不支援

 匹配如<div id=”content”></div>或<div id=”dummytent”></div>的元素,就是匹配屬性值以value結尾的元素。

7. 基礎選擇器[attr*=value](如 div[id*=ten] )IE5.5~IE6不支援

 匹配如<div id=”content”></div>或<div id=”dummytent”></div>的元素,就是匹配屬性值含value的元素。

 

偽類選擇器


 

  我們可將偽類選擇器再細分一下,以便記憶!

  結構性偽類選擇器

    1. E:first-child:當元素E作為其父元素下的第一個子元素時,匹配成功。IE5.5~IE6不支援

    2. E:root:當元素E為文件的根元素(就是HTMLHtmlElement元素)時,匹配成功。(IE均不支援)

    3. E:nth-child(n):當元素E作為其父元素下第N個子元素時,匹配成功。n從1開始。(IE5.5~IE8不支援)

    4. E:nth-last-child(n):與E:nth-child(n)效果一樣,只不過是反方向遍歷。n從1開始。(IE5.5~IE8不支援)

    5. E:nth-of-type(n):當元素E為其父元素下同類標籤的第N個時,匹配成功。n從1開始。(IE5.5~IE8不支援)

    6. E:nth-last-of-type(n):與E:nth-last-of-type(n)效果一樣,只不過時反方向遍歷。n從1開始。(IE5.5~IE8不支援)

    7. E:last-child:當E元素作為其父元素下最後一個子元素時,匹配成功。(IE5.5~IE8不支援)

    8. E:first-of-type:與E:nth-of-type(1)效果一樣。(IE5.5~IE8不支援)

    9. E:last-of-type:與E:nth-last-of-type(1)效果一樣。(IE5.5~IE8不支援)

    10.E:only-child:當E元素為其父元素下的唯一一個子元素,匹配成功。(IE5.5~IE8不支援)

    11.E:only-of-type:當E元素為其父元素下的唯一一個該標籤型別的子元素時,匹配成功。(IE5.5~IE8不支援)

    12.E:empty:當E元素下不包含任何子元素時,匹配成功。注意:文字節點也被視為子元素。(IE5.5~IE8不支援)

  注意:nth-child(n)中n的合法寫法如下

  ①.純數字,指定位置索引,索引從1開始;

  ②.n,指定匹配所有位置索引,n會自動從1開始自增長,至於何時才停止就不得而知了;

  ③.純數字n,如2n,指定匹配偶數位置索引的元素,n會自動從1開始自增長,至於何時才停止就不得而知了;

  ④.純數字n +/- 純數字,如2n+1,指定匹配奇數位置索引的元素,n會自動從1開始自增長,至於何時才停止就不得而知了。

  動態偽類選擇器(E:hover,IE5.5~7只支援在a元素上應用,IE8+支援在其他元素上使用)

  1. E:link:當元素E(a標籤)未被點選時,匹配成功。

  2. E:visited:當元素E(a標籤)點選過時,匹配成功。

    3. E:hover:必須在E:link、E:visited後宣告才有效。當元素E(IE5.5~7時為a標籤,IE8+可為其他標籤)正被滑鼠懸停時,匹配成功。

    4. E:active:必須在E:hover後宣告才有效。當滑鼠已經在元素E(a標籤)按下,但未釋放左鍵時,匹配成功。

    5. E:focus:當元素E(元素E必須為可以接收鍵盤或使用者輸入的元素)獲得焦點時,匹配成功。(IE8的標準模式開始支援)

  語言 :lang偽類選擇器(IE5.5~8不支援)

   1. E:lang(c):當元素的lang屬性等於c時,則匹配成功。

  UI元素狀態偽類選擇器(IE5.5~8不支援

     1. E:enabled:元素E(E為表單元素)可用時,匹配成功。

     2. E:disabled:元素E(E為表單元素)不可用時,匹配成功。

     3. E:checked:元素E(E為input[type=radio]或input[type=checkbox]元素)被鉤選時,匹配成功。

  否定偽類選擇器(IE5.5~8不支援

     1. E:not(其他型別的選擇器):當元素E不符合其他型別的選擇器條件時,匹配成功。

   E:target 偽類選擇器( IE瀏覽器完全不支援:target偽類,另一個小問題就是Opera 在使用“前進”和後退按鈕時不支援該選擇器)

     1. E:target:當你使用錨點(片段識別符號 fragment identifier)的時候,比如,http://www.smashingmagazine.com/2009/08/02/bauhaus- ninety-years-of-inspiration/#comments,這“#comments”就是一個片段識別符號,你就可以使 用:target偽類來控制目標的樣式。

   ::selection 偽類選擇器IE5.5~8不支援

     1. E::selection:被使用者選區的元素部分

 

偽元素選擇器


  偽元素就是瀏覽器自動在匹配的匹配元素前、後增加的元素,或者是擷取匹配元素內的一部分。

1. E:before(新寫法E::before):用於向元素E前新增內容(IE8的標準模式開始支援)

2. E:after(新寫法E::after):用於向元素E後新增內容(IE8的標準模式開始支援)

示例:

複製程式碼
<style type="text/css">
div:before{
  content: "beforeDiv"
}
div:after{
  content: "afterDiv"
}
</style>
<div>content</div>
複製程式碼

效果是: beforeDivcontentafterDiv 

3. E:first-line(新寫法E::first-line):僅僅當元素E為塊級元素時有效。用於向元素E中的文字的首行新增特殊樣式。

4. E:first-letter(新寫法E::first-letter):用於向元素E的首個字母新增特殊樣式

5. E:input-placeholder:用於向元素E的placeholder新增特殊樣式。由於未成為W3C規範,因此需要加瀏覽器廠商字首,具體如下

複製程式碼
/*for old version of ff*/
input:-moz-input-placeholder{
}
input:-ms-input-placeholder{
}
/*for modern browsers*/
input::-webkit-input-placeholder{
}
input::-moz-input-placeholder{
}
複製程式碼

而且僅有以下屬性可用:color、font-size、font-style、font-weight、letter-spacing、line-height、padding、text-align、text-decoration。

注意:

/* 由於偽元素選擇器必須為最後一個選擇器,因此下列css樣式將失效 */
div::before div{
    width: 100px;
    height: 100px;
    background-color: red;   
}

 

三、選擇器的優先順序計分規則                      

  優先順序是決定不同選擇器的相同樣式規則對同一元素的生效情況,優先順序高的將覆蓋優先順序低的樣式規則。而優先順序又受到樣式來源和選擇器特殊性的影響,下面我們一起來了解以下。

  1. 來源

    行內樣式 > 頁內樣式 > 外部引用樣式 > 瀏覽器預設樣式

  2. 特殊性(由四個緯度組合)

選擇器型別 緯度(a,b,c,d)
行內樣式 1,0,0,0
ID選擇器 0,1,0,0
類選擇器、屬性選擇器、偽類選擇器 0,0,1,0
元素(型別)選擇器,偽元素(型別)選擇器 0,0,0,1
通用元素選擇器、偽類:not選擇器 0,0,0,0

                  注意:多種選擇器型別時,同位疊加即可得到總緯度。

                                                                   參考:http://www.w3.org/TR/CSS21/cascade.html#specificity

  3. 計算優先順序的流程

     (a). 首先根據選擇器型別計算出總緯度

     (b). 若緯度相同則比較來源

     (c). 若前兩者相同,則後面宣告的優先順序高。

  4. 通過!important提高優先順序(IE5.5~6不支援)

    通過在樣式規則後面新增!important關鍵詞,可以將該樣式規則提高到最高優先順序。

.test{
  color: red !important;
  color: blue;
}

   IE5.5~6下, 匹配元素的文字為blue;而其他瀏覽器則為藍色;IE7+下就顯示紅色。

   但!important不是一個優雅的辦法,而且會使得樣式難以除錯,下面是時是使用建議

   1. 永遠不要在全域性CSS規則中使用;

   2. 永遠不要在自制的外掛中使用;

   3. 只在需要覆蓋全域性或外部外掛的css規則(如Extjs、YUI外掛的樣式)的特定頁面中才使用;

   4. 首先考慮使用優先順序來解決問題而不是!important.

   適合使用的場景:

        將行內樣式提取出來時,但此時已經有一個全站樣式了;

   覆蓋!important:

/* 寬度為200px */
E {
  width: 200px; !important   
  width: 100px;
}
/* 寬度為300px */
E {
  width: 200px; important
  width: 100px;
  width: 300px; important
}

   參考:https://developer.mozilla.org/zh-CN/docs/Web/CSS/Specificity

 

 5. 偽類 :not 選擇器緯度為0,0,0,0

  偽類 :not 選擇器自身緯度為0,0,0,0 ,但其括號內部的選擇器緯度則和上述表格一致。 div:not(.content) { width: 100px; } 優先順序計算如下:

div ── 緯度 0,0,0,1

:not ── 緯度 0,0,0,0

.content ── 緯度 0,0,1,0

總緯度 ── 0,0,1,1

 

6. IE6中的bug

IE6中偽類 :hover 、 :active 和 :visited 選擇器的緯度不是0,0,1,0,而是0,0,2,0。

複製程式碼
// 緯度是0,0,2,1
.cls1 .cls2 a{
  color: red;
}
// IE6下的緯度是0,0,2,1
// IE7+的緯度是0,0,1,1
a:hover{
  color: blue;
}
複製程式碼

參考:

http://www.cnblogs.com/ddshou/archive/2009/05/05/1449768.html

http://www.cnblogs.com/ddshou/archive/2009/05/05/1449770.html

 

四、瀏覽器解析選擇器的順序——key selector(關鍵字查詢)           

  就是從右向左解析選擇器,這樣效率就更高了。

 

五、一起做題木吧!                        

A. img.thumb:after,總緯度是0,0,1,2

B.[data-job=”frontend”]::first-letter,總緯度是0,0,1,1

C. #main::before,總緯度是0,1,0,1

D. [type=”checkbox”]:checked,總緯度是0,0,2,0

E. ul#shop-list,總緯度是0,1,0,1

由於該題目假定樣式來源一致,因此樣式優先順序相同的就是C和E了。

 

六、參考                                 

  CSS選擇器 http://www.cnblogs.com/liontone/archive/2010/12/29/1920437.html

  http://www.w3school.com.cn/cssref/css_selectors.asp

  http://blog.163.com/hongshaoguoguo@126/blog/static/1804698120134491240171/

  http://blog.csdn.net/stationxp/article/details/38736261

如何聯絡我:【萬里虎】www.bravetiger.cn
【QQ】3396726884 (諮詢問題100元起,幫助解決問題500元起)
【部落格】http://www.cnblogs.com/kenshinobiy/


相關文章