1 StyleSheet 一張 StyleSheet 由一系列 Rules 組成,這些 Rules 可以分成 2 大類: 1 Style Rule 2 At-Rule 下麵的例子展示了 Style Rule 和 At-Rule: // Style Rule div { background-colo ...
1 StyleSheet
一張 StyleSheet 由一系列 Rules 組成,這些 Rules 可以分成 2 大類:
1 Style Rule
2 At-Rule
下麵的例子展示了 Style Rule 和 At-Rule:
// Style Rule div { background-color: red; font-size: 12px; } // At-Rule @media print { body { font-size: 10pt; } }
上面代碼的第 1 個 Rule 是 Style Rule,表示 <div> 標簽的背景色是紅色,字型大小是 12px。
代碼的第 2 個 Rule 是 At-Rule,At-Rule 都以 '@' 字元開始。@media 表示如果列印 HTML,HTML 中的字型大小使用 10pt。
2 Style Rule
Style Rule 由 2 部分組成:
1 selector list
2 聲明塊
如下圖所示:
selector list 定義一系列 selector,表示聲明塊應該應用在哪些 HTML 標簽上。比如上圖中的 selector list 就表示,background-color 和 font-size 應用在 <div> 和 <p> 標簽上。
有關 Style Rule 的 selector,後面會有更詳細的介紹。
3 Qualified Rule
從定義上講,Style Rule 只是 Qualified Rule 的一種特殊形式,Qualified Rule 的組成如下圖所示:
從圖上可以看到,Qualifed Rule 由 prelude 和聲明塊兩部分組成。如果 prelude 是 selector list,那麼此時的 Qualified Rule 就是 Style Rule。
那麼什麼時候會使用非 Style Rule 的 Qualified Rule 呢?一個場景是 At-Rule @keyframe 定義的動畫:
div { // 1. 使用 @keyframe 定義的 slide-right 動畫 animation-name: slide-right; animation-duration: 2s; } // 2. 使用 @keyframe 定義 slide-right 動畫 @keyframes slide-right { // 3. from 50% to 就是一個 Qualified Rule,但是不是 Style Rule from { margin-left: 0px; } 50% { margin-left: 110px; opacity: 1; } 50% { opacity: 0.9; } to { margin-left: 200px; } }
上面代碼註釋 1 處 div 標簽使用了 @keyframe 定義的一個動畫 slide-right。
代碼註釋 2 處就是動畫的定義,在定義內部,from、50%、to 處的 Rule 就是一個 Qualified Rule,但是不是 Style Rule,如註釋 3 所示。
非 Style Rule 的 Qualifed Rule 不能作為 CSS 樣式表的頂層 Rule,CSS 樣式表的頂層 Rule 只能是 Style Rule 或者 At-Rule。
4 聲明塊
聲明塊中的聲明(Declaration)分成 2 類:
1 屬性聲明(property declaration)
2 描述符聲明(descriptor delcaration)
在 Qualifed Rule 中的聲明稱為屬性聲明,而在 At-Rule 中的聲明稱為描述符聲明。屬性聲明比較常見,描述符聲明的例子如下所示:
@font-face { // 描述符聲明 font-family: overridden-font; }
本質上來看,屬性聲明和描述符聲明沒有什麼區別,只是所在的位置不一樣。
無論是屬性聲明,還是描述符聲明,都由聲明名和聲明值組成。
5 At-Rule
At-Rule 以 '@' 字元開頭。
At-Rule 分成 2 大類:
1 聲明式 At-Rule(statement At-Rule)
2 塊式 At-Rule(Block At-Rule)。
聲明式 At-Rule 就像一條語句一樣,以分號結尾。@cahrset 就是一個聲明式 At-Rule:
@charset "utf-8";
塊式 At-Rule 由 {} 包圍,上面的 @media 就是一個塊式 At-Rule。
塊式 At-Rule 裡面可以包含描述符聲明,比如:
@font-face { // 描述符聲明 font-family: overridden-font; }
可以包含 Qualifed Rule,比如:
@media print { // Qualifed Rule,也是 Style Rule body { font-size: 10pt; } }
可以包含其他 At-Rule,比如:
@supports (display: flex) { @media screen and (min-width: 900px) { article { display: flex; } } }
6 Selector
Style Rule 中的 Selector 用來匹配 HTML 中的標簽,以便決定聲明塊中的聲明運用在哪些 HTML 標簽上,比如:
div { background-color: red; }
表示 HTML 中的所有 div 標簽背景色都要是紅色。
Selector 分為 5 類: 簡單 Selector(Simple Selector)、複合 Selector(Compound Selector)、組合 Selector(Complex Selector)、Selector List。
6.1 Simple Selector
簡單 Selector 分為 6 種情形:
1 類型 Selector (Type Selector)
2 通用 Selector (Universal Selector)
3 屬性 Selector (Attribute Selector)
4 類 Selector (Class Selector)
5 ID Selector
6 偽類 Selector (Pseudo-Class Selector)
6.1.1 類型 Selector
類型 Selector 就是 HTML 中的標簽名,比如:
div { background-color: red; }
中的 div 就是類型 Selector,匹配 HTML 中的所有 <div> 標簽。
6.1.2 通用 Selector
通用 Selector 是一種特殊的類型 Selector,它匹配任意一個 HTML 標簽,使用字元 '*' 表示,比如:
* { font-size: 13px; }
表示 HTML 中每一個標簽的字型大小都是 13px。
如果通用 Selector 和其他簡單 Selector 組成複合 Selector,那麼通用 Selector 不起作用,也就是說:
*.news <===> 等價於 .news
*#item <===> 等價於 #item
6.1.3 命名空間
@namespace 定義一個命名空間,相關語法如下:
@namespace <namespace-prefix>? [<string>|<url>]
其中,namespace-prefix 可以省略,如果省略了 namespace-prefix,那麼就是定義了一個預設命名空間。
定義命名空間的例子如下:
// 定義了預設命名空間
@namespace "http://www.w3.org/1999/xhtml";
// 定義了一個命名空間,namespace-prefix 是 svg
@namespace svg "http://www.w3.org/2000/svg";
// 以字元串定義命名空間
@namespace xml "XML-namespace-URL";
對於定義在一張 CSS 樣式表裡面的 namespace-prefix,只在當前 CSS 樣式表可見。
The namespace prefix is declared only within the style sheet in which its @namespace rule appears. It is not declared in any style sheets importing or imported by that style sheet, nor in any other style sheets applying to the document.
如果一張樣式表裡面聲明瞭多個命名空間,只有最後一個命名空間有效。
If a namespace prefix or default namespace is declared more than once only the last declaration shall be used.
類型 Selector 和通用 Selector 可以結合命名空間使用,這樣類型 Selector 和通用 Selector 只匹配位於指定命名空間的 HTML 標簽。
相關語法如下:
// ns 表示命名空間
// E 表示類型 Selector 或者通用 Selector
// 匹配位於命名空間 ns 的 HTML 標簽 E
ns|E
// 匹配位於任意命名空間的 HTML 標簽 E,如果 E 不屬於任何命名空間,也會匹配上
*|E
// 匹配不屬於任何命名空間的 HTML 標簽 E
|E
// 如果沒有預設命名空間,這個語法等價於 *|E
// 如果有預設命名空間,這個語法等價於 ns|E
E
下麵看一些例子:
@namespace foo url(http://www.example.com); foo|h1 { color: blue } /* first rule */ foo|* { color: yellow } /* second rule */ |h1 { color: red } /* ...*/ *|h1 { color: green } h1 { color: green }
上面代碼定義了一個命名空間 foo。
第 1 條 Rule 匹配 HTML 中所有位於命名空間 foo 的 <h1> 標簽。
第 2 條 Rule 匹配 HTML 中位於命名空間 foo 的所有標簽。
第 3 條 Rule 匹配不屬於任何命名空間的 <h1> 標簽。
第 4 條 Rule 等價 HTML 中所有 <h1> 標簽,這些 <h1> 標簽可以位於任意命名空間,也可以不位於任何命名空間。
第 5 條 Rule 等價於第 4 條 Rule,因為沒有定義預設命名空間。
6.1.4 屬性 Selector
屬性 Selector 匹配 HTML 標簽中具有相應屬性的標簽,比如:
[class="example"]
匹配所有具有 class 屬性的 HTML 標簽,假設一個 <span> 標簽具有 class 屬性並且屬性值是 “example",那麼這個 <span> 標簽就被匹配到:
<span class="example">Hello, World!</span>
屬性 Selector 的語法如下:
// 匹配具有屬性名為 attr 的 HTML 標簽
[attr]
// 匹配具有屬性名為 attr,屬性值為 val 的 HTML 標簽
[attr=val]
// 匹配具有屬性名 attr 的 HTML 標簽,並且該屬性值是一個由空格分割的 list,
// 如果這個屬性值 list 裡面有一個值是 val,那麼就匹配上。
// 如果 val 本身是一個空字元串或者包含空格的字元串,那麼就匹配不上任何 HTML 標簽
[attr~=val]
// 匹配具有屬性名 attr 的 HTML 標簽,並且該屬性值為 val 或者以 val- 開頭
[attr|=val]
// 匹配具有屬性名 attr 的 HTML 標簽,並且屬性值以 val 開頭。
// 如果 val 是空字元串,那麼匹配不到任何 HTML 標簽
[attr^=val]
// 匹配具有屬性名 attr 的 HTML 標簽,並且屬性值以 val 結尾。
// 如果 val 是空字元串,那麼匹配不到任何 HTML 標簽
[attr$=val]
// 匹配具有屬性名 attr 的 HTML 標簽,並且屬性值至少包含 val。
// 如果 val 是空字元串,那麼匹配不到任何 HTML 標簽
[attr*=val]
具體例子如下:
// 匹配具有 title 的 <h1> 標簽
h1[title]
// 如果 <span> 標簽有一個 class 屬性,並且屬性值為 example,則匹配
span[class="example"]
// 如果 <a> 標簽的 rel 屬性值是 "copyright copyleft copyeditor",則匹配
a[rel~="copyright"]
// 如果 <a> 標簽的 hreflang 的屬性值為 en 或者 en-US,則匹配
a[hreflang|="en"]
// 如果 <object> 標簽的 type 屬性以 image/ 開頭,則匹配
object[type^="image/"]
// 如果 <a> 標簽的 href 屬性以 .html 結尾,則匹配
a[href$=".html"]
// 如果 <p> 標簽的 title 屬性值為 "hello, world",則匹配
p[title*="hello"]
和類型 Selector、通用 Selector 一樣,屬性 Selector 的屬性名 attr 也可以結合命名空間。不同的是,類型 Selector、通用 Selector 可以結合預設命名空間,屬性 Selector 不能結合預設命名空間。
相關語法如下:
@namespace foo "http://www.example.com"; [foo|attr=val] { color: blue } [*|attr] { color: yellow } [|attr] { color: green } [attr] { color: green }
上面代碼定義了一個命名空間 foo。
第 1 條 Rule 匹配屬性名 attr 位於命名空間 foo 的 HTML 標簽。
第 2 條 Rule 匹配屬性名 attr 位於任意命名空間或者不位於任何命名空間的 HTML 標簽。
第 3 條 Rule 和第 4 條 Rule 是等價的,只匹配 attr 不屬於任何命名空間的 HTML 標簽。
6.1.5 類 Selector
類 Selector 以 '.' 字元開始。
例子如下:
.test { font-size: 20px; }
這個類 Selector 匹配第 1 個 和第 3 個 <h1> 標簽,不匹配第 2 個 <h1> 標簽,因為第 2 個 <h1> 標簽沒有對應的 class:
<h1 class="test">標題一</h1>
<h1>標題二</h1>
<h1 class="test">標題三</h1>
6.1.6 ID Selector
ID Selector 以 '#' 字元開始,ID Selector 必須是唯一的,因此只匹配唯一的 HTML 標簽:
例子如下:
#test { font-size: 20px; }
這個 ID Selector 匹配第 1個 <h1> 標簽:
<h1 id="test">標題一</h1>
<h1>標題二</h1>
<h1>標題三</h1>
6.1.7 偽類 Selector
有一些匹配行為,上述的簡單 Selector 無法表達,比如有一個場景是,當用戶滑鼠停留在 <h1> 標簽上,<h1> 標簽才變換背景色。為了表達"用戶停留"這個行為,就需要使用偽類 :hover,例子如下:
h1:hover { background-color: red; }
偽類 Selector 以 ':' 開頭,可以分成普通偽類和函數偽類。
:hover 就是普通偽類,:lang() 就是一個函數偽類。
偽類必須結合類型 Selector 和通用 Selector 才能使用,必須跟在類型 Selector 和通用 Selector 後面。
6.2 複合 Selector
複合 Selector 由一個或者多個簡單 Selector 組成,如果有多個簡單 Selector,簡單 Selector 之間不能由 Combinator 連接。
一個複合 Selector 的所有簡單 Selector 匹配完成,整個複合 Selector 才算匹配,比如:
div#test { background-color: red; }
只匹配具有 id 屬性並且 id 屬性等於 test 的 <div> 標簽:
<div>Test1</div>
<div id="test">Test2</div>
如果類型 Selector 或者通用 Selector 出現在複合 Selector 中,那麼類型 Selector 和通用 Selector 必須是複合 Selector 中的第一個簡單 Selector。
同時,如果複合 Selector 中已經有了一個類型 Selector 或者通用 Selector,就不可以有其他的類型 Selector 和通用 Selector。
在複合 Selector 中,類 Selector、ID Selector、屬性 Selector、偽類 Selector 都稱為 Subclass-Selector。
6.3 複合偽元素 Selector (Pseduo-Compound Selector)
和偽類(Pseduo-Class)一樣,偽元素(Pseduo-Element)也是用來表達 HTML 標簽無法表達的信息。
與偽類不同的是,偽類側重表達某種狀態或者行為,而偽元素側重表達 HTML 文檔的某部分內容,比如 HTML 文檔某行的首字母,就可以使用偽元素 ::first-letter 來表示。
複合偽元素 Selector 的組成首先要有一個偽元素,這個偽元素的後面可以跟一個偽類,這個偽元素的前面可以有一個複合 Selector或者另外一個複合偽元素 Selector。因此下麵兩種複合偽元素 Selector 都是合法的:
.foo::before:hover
.foo::before::marker
複合偽元素 Selector 中不能出現 Combinator。
複合微元素 Selector 是用來匹配偽元素的,要成功匹配偽元素需要滿足:
1 被匹配的偽元素需要是複合偽元素 Selector 中的偽元素;
2 匹配複合偽元素 Selector 中的偽類;
3 匹配複合偽元素 Selector 中的複合 Selector,這個被匹配的 HTML 標簽被稱為 Originating Element。
如果複合偽元素 Selector 沒有複合 Selector,那麼預設使用通用 Selector,也就是說,下麵兩種複合偽元素 Selector 是等價的:
::before <====> 等價於 *::before
本質上講,複合偽元素 Selector 跟複合 Selector 不一樣,如果一個地方只能使用複合 Selector,那麼就不能使用複合偽元素 Selector。
NOTE: A pseudo-compound selector is not a compound selector, and can’t be used in places that expect a compound selector only. Pseudo-compound selectors act as if they carry a combinator with themselves, expressing their relationship with their originating element, just as the > combinator expresses a relationship with a parent element.
6.4 組合 Selector
組合 Selector 是由 Combinator 連接的 2 個複合 Selector。
1 Descendant Combinator
2 Child Combinator
3 Next-Sibling Combinator
4 Subsequence-Sibling Combinator
6.4.1 Descendant Combinator
後代 Combinator,由空格表示,匹配一個 HTML 標簽的所有後代標簽,比如:
h1 em
會匹配 <h1> 標簽的所有後代 <em> 標簽:
<h1>This <span class="myclass">headline is <em>very</em> important</span></h1>
6.4.2 Child Combinator
子 Combinator,由 '>' 表示,匹配一個 HTML 標簽的所有子標簽,比如:
body > p
會匹配 <body> 標簽的所有子 <p> 標簽:
<body>
<p>段落1</p>
<p>段落2</p>
<p>段落3</p>
</body>
6.4.3 Next-Sibling Combinator
下一個相鄰兄弟節點 Combinator,由 '+' 表示,直接看例子:
div + p
會匹配 <div> 標簽後面第一個 <p> 標簽,而不會匹配其他 <p> 標簽:
<p>上一個兄弟節點</p> <div>我要匹配</div> <p>下一個兄弟節點</p> <p>下下個兄弟節點</p>
6.4.4 Subsequence-Sibling Combinator
後續兄弟 Combinator,由 '~' 表示,直接看例子:
div ~ p
會匹配 <div> 標簽後面所有的兄弟 <p> 標簽,而不會匹配 <div> 標簽上面的兄弟 <p> 標簽:
<p>上一個</p> <div>DIV1</div> <div>DIV2</div> <p>下一個</p> <p>下下一個</p>
7 Selector List
由逗號 ',' 連接的簡單 Selector、複合 Selector、組合 Selector 組成,比如:
div, h1#item, p + span { background-color: red; } h1, h2, h3 { background-color: green; }
參考連接
List of CSS descriptors, both proposed and standard