W3C 使用特定的語法來定義所有可能在 CSS 屬性中使用的值。如果你曾經看過 CSS 規範,你可能已經見過這種語法的使用 – 比如 border-image-slice
語法。讓我們來看看:
1 |
<'border-image-slice'> = [<number> | <percentage>]{1,4} && fill? |
這個語法可能很難理解-如果你不知道其中的各個符號和他們是怎樣生效的話。但是,這是值得花時間去學習的。如果你理解了 W3C 是怎樣定義這些屬性值,你就能理解 W3C 的任何 CSS 規範。
巴科斯正規化
我們將從巴科斯正規化開始,因為這會幫助我們理解 W3C 的屬性值語法。 巴科斯正規化( BNF )是一種用來描述計算機語言語法的符號集。它的設計是明確的,所以對於如何表示語言這方面不存在分歧或歧義。 如今廣泛使用的是巴科斯正規化的擴充套件和編譯版本,包括擴充套件巴科斯正規化( EBNF )和擴充巴科斯正規化( ABNF )。 一個 BNF 規範是一組按照下面的方式書寫的規則:
1 |
<symbol> ::= __expression__ |
左邊的部分總是一個非終結符,隨後是一個 ::=
符號,這個符號的意思是“可以被替換為”。右邊是一個 __expression__
,包含一個或更多用來推導左邊符號的含義的符號。 BNF 的基本規範說,“左邊的任何都可以被右邊的替換”。
非終結符和終結符
非終結符是可以被替換或再細分的符號。在 BNF 中,非終結符出現在 < >
中。在下面的例子中,<integer>
和<digit>
是非終結符。
1 |
<integer> ::= <digit> | <digit><integer> |
終結符就代表一個值不可被替換或者再細分。在下面的例子中,所有的數值都是終結符。
1 |
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
CSS 屬性值語法
雖然 W3C 的 CSS 屬性值語法是基於 BNF 的概念,但它還是有差異的。相似之處在於它開始於非終結符,不同之處在於它使用“組合值”這種表示式來描述符號。 在下面的例子中,<line-width>
是一個非終結符,<length>
,thin
,medium
和 thick
就是組合值。
1 |
<line-width> = <length> | thin | medium | thick |
組合值
有四種型別的組合值:關鍵詞,基本資料型別,屬性資料型別和非屬性資料型別。
1.關鍵詞
關鍵詞出現時不帶引號或者尖括號。它們被用作屬性值。因為它們不能被替換或者進一步細分,所以它們是終結符。在下面的例子中,thin
,medium
和 thick
都是關鍵詞。這意味著它們可以被用作我們 CSS 中的值。
1 |
<line-width> = <length> | thin | medium | thick |
2.基本資料型別
基本資料型別定義核心值,如<length>
和<color>
。它們是非終結值因為它們可以被實際的長度值或者顏色值來替換。在下面的例子中,<color>
符號是一個基本資料型別。
1 |
<'background-color'> = <color> |
這個<color>
在我們的 CSS 中可以被一個真實的顏色值替換,使用一個關鍵詞,一個擴充套件的關鍵詞,一個 RGB 顏色值,RGBA 值,HSL 或者 HSLA 值,或者 transparent
這個關鍵詞。
1 2 3 4 5 6 7 |
.example { background-color: red; } .example { background-color: honeydew; } .example { background-color: rgb(50%,50%,50%); } .example { background-color: rgba(100%,100%,100%,.5); } .example { background-color: hsl(280,100%,50%); } .example { background-color: hsla(280,100%,50%,0.5); } .example { background-color: transparent; } |
3.屬性資料型別
屬性資料型別是一個用來定義屬性真實值的一個非終結符號。它用尖括號包住屬性的名字(使用引號包住)。在下面的例子中,<'border-width'>
字元是一個屬性資料型別。
1 |
<'border-width'> = <line-width>{1,4} |
屬性資料型別可能會直接作為屬性出現在我們的 CSS 中。在下面的例子中,border-width
屬性就被用來為.example
類名定義一個 2px 的邊框。
1 |
.example { border-width: 2px; } |
4.非屬性資料型別
非屬性資料型別是一個和屬性名稱不相同的非終結符。然而,它定義了某個屬性的各方面。舉例來說,<line-width>
不是一個屬性,但是它是一個定義了各種<border>
屬性的資料型別。
1 2 |
<line-width> = <length> | thin | medium | thick <'border-width'> = <line-width>{1,4} |
組合值選擇符
組合值可以通過下面五種方法之一被用到屬性值選擇符中。
1.相鄰值
組合值中一個接著一個的寫法意味著這些值都必須以給定的順序出現。在下面的例子中,這種語法列出了3個不同的值:value1
, value2
和 value3
。在 CSS 規則中,這三個值以正確的順序出現在屬性語法中才是有效的。
1 2 3 4 5 |
/* Component arrangement: all in given order */ <'property'> = value1 value2 value3 /* Example */ .example { property: value1 value2 value3; } |
2.&&
用兩個&符號(&&
)分隔的兩個或者多個值意味著它們必須出現,以任何順序。在下面的例子中,這種語法列出兩個值,通過 && 分隔。CSS 規則表明這兩個值必須都要出現但是可能是任何順序出現。
1 2 3 4 5 6 |
/* Component arrangement: all, in any order */ <'property'> = value1 && value2 /* Examples */ .example { property: value1 value2; } .example { property: value2 value1; } |
3.|
用 |
符號分隔的兩個或者多個值意味著它們中的一個必須出現。在下面的例子中,這種語法列出 3 個值,通過 | 分隔。下面的 CSS 規則展示了 3 種可能的選擇。
1 2 3 4 5 6 7 |
/* Component arrangement: one of them must occur */ <'property'> = value1 | value2 | value3 /* Examples */ .example { property: value1; } .example { property: value2; } .example { property: value3; } |
4.||
用 ||
分隔的兩個或者多個值意味著它們中的一個或者多個必須出現,以任意的順序。在下面的例子中,這種語法列出了 3 個值,它們通過 || 分隔。當你寫 CSS 規則來匹配這個語法時,有很多可用的選擇 – 你可以使用一個,兩個,或者三個值,以任意的順序。
1 2 3 4 5 6 7 8 9 10 |
/* Component arrangement: one or more in any order */ <'property'> = value1 || value2 || value3 /* Examples */ .example { property: value1; } .example { property: value2; } .example { property: value3; } .example { property: value1 value2; } .example { property: value1 value2 value3; } ...etc |
5.[]
用 []
包圍的兩個或者多個值意味著元件內部是一個單獨的分組。在下面的例子中,這種語法列出了 3 個值,但是其中兩個出現在 [] 內,所以它們是一個單獨的分組。在 CSS 規則中有兩個選擇是可用的:value1
和 value3
或者 value2
和 value3
。
1 2 3 4 5 6 |
/* Component arrangement: a single grouping */ <'property'> = [ value1 | value2 ] value3 /* Examples */ .example { property: value1 value3; } .example { property: value2 value3; } |
組合值疊加
組合值也可以使用下面的 8 種方法被疊加。
1.?
?
表示前置型別,一個詞或一個組可以選擇出現零次或者出現一次。在下面的例子中,第二個值被放在[]裡面和一個’,’在一起。放在這一組後面的 ?
意味著 value1 必須出現,但是我們也可以使用 value1
和 value2
,用逗號分隔。
1 2 3 4 5 6 |
/* Component multiplier: zero or one time */ <'property'> = value1 [, value2 ]? /* Examples */ .example { property: value1; } .example { property: value1, value2; } |
2.*
*
表示前置型別,一個詞或一個組出現零次或者多次。在下面的例子中,第二個值被放在[]裡面和一個’,’在一起。放在這一組後面的 *
意味著 value1必須出現,但是我們也可以使用任意次 <value2>
,用逗號分隔。
1 2 3 4 5 6 7 8 9 |
/* Component multiplier: zero or more times */ <'property'> = value1 [, <value2> ]* /* Examples */ .example { property: value1; } .example { property: value1, <value2>; } .example { property: value1, <value2>, <value2>; } .example { property: value1, <value2>, <value2>, <value2>; } ...etc |
3.+
+
表示前置型別,一個詞或一個組可以選擇出現一次或者出現多次。在下面的例子中,value後面的 +
意味著 <value>
可以出現一次或者多次 – 不需要逗號分隔。
1 2 3 4 5 6 7 8 |
/* Component multiplier: one or more times */ <'property'> = <value>+ /* Examples */ .example { property: <value>; } .example { property: <value> <value>; } .example { property: <value> <value> <value>; } ...etc |
4.{ A }
{}
中包含一個單一的數字表示前置型別,一個詞或一個組出現 A
次。在下面的例子中,value的例項必須出現兩次,以便使宣告有效。
1 2 3 4 5 |
/* Component multiplier: occurs A times */ <'property'> = <value>{2} /* Examples */ .example { property: <value> <value>; } |
5. {A, B}
{}
中包含兩個以逗號分隔的數字對錶示前置型別,一個詞或一個組出現至少 A
次,至多 B
次。在下面的例子中,value
出現至少一次,至多三次用來定義這個屬性,這些值不需要用逗號分隔。
1 2 3 4 5 6 7 |
/* Component multiplier: at least A and at most B */ <'property'> = <value>{1,3} /* Examples */ .example { property: <value>; } .example { property: <value> <value>; } .example { property: <value> <value> <value>; } |
6.{A,}
這裡的 B
可以省略,代表至少出現一次,對於上限沒有限制。在下面的例子中,value
至少出現一次,但是也可以增加任意數量value
。這些值不需要用逗號分隔。
1 2 3 4 5 6 7 8 |
/* Component multiplier: at least A, with no upper limit */ <'property'> = <value>{1,} /* Examples */ .example { property: <value>; } .example { property: <value> <value>; } .example { property: <value> <value> <value>; } ...etc |
7.#
#
表示前置型別,一個詞或者一個組出現一次或者多次,用逗號分隔。在下面的例子中,可以使用一個或者多個value
,每個由逗號分隔。
1 2 3 4 5 6 7 8 |
/* Component multiplier: one or more, separated by commas */ <'property'> = <value># /* Examples */ .example { property: <value>; } .example { property: <value>, <value>; } .example { property: <value>, <value>, <value>; } ...etc |
8.!
一個組後面的 ! 表示這個組是必需的並且至少產生一個值。在下面的例子中,這種語法列出了 3 個值,通過 |
分隔。下面的 CSS 規則展示了三種可能的選擇:
1 2 3 4 5 6 |
/* Component multiplier: required group, at least one value */ <'property'> = value1 [ value2 | value3 ]! /* Examples */ .example { property: value1 value2; } .example { property: value1 value3; } |
<'text-shadow '>
語法:一個例子
讓我們來看看 <'text-shadow'>
這個屬性作為例子。讓我們來看看規範中是如何定義這個屬性的:
1 |
<'text-shadow'> = none | [ <length>{2,3} && <color>? ]# |
我們可以分解這些符號:
|
代表我們可以使用關鍵詞none
或組[]
#
代表我們可以使用一次或多次這個組,用逗號分隔。- 在組的內部,
{2,3}
代表我們可以使用兩到三個<length>
&&
代表我們必需包含所有的值,但是它們可以是任意順序。- 僅僅是為了更加微妙,
<color>
後面包括一個?
,這意味著它可以出現零次或一次。
用通俗的語言可以表述為:
不指定或指定一個或多個組,這個組包含 2 – 3 個表示長度的值和一個可選額顏色值。長度值和顏色值可以寫成任意順序。
這意味著我們用不同的方式來寫我們的 text-shadow
屬性。舉例來說,我們可以設定 text-shadow
屬性為 none
:
1 |
.example { text-shadow: none; } |
我們可以只寫兩個長度值,這意味著我們將設定陰影的水平和垂直偏移,但是沒有模糊半徑或者顏色值。 因為沒有設定模糊半徑,初始值是 0;所以,陰影是尖銳的。顏色沒有定義,文字的顏色將用於陰影的顏色。
1 |
.example { text-shadow: 10px 10px; } |
如果我們使用 3 個長度值,我們就為陰影設定了模糊半徑,水平和垂直偏移。
1 |
.example { text-shadow: 10px 10px 10px; } |
我們可以包含一個顏色值,它可以放在兩個或者三個長度值的前面或後面。在下面的例子中,紅色的顏色值可以被放在一組值的任一端。
1 2 |
.example { text-shadow: 10px 10px 10px red; } .example { text-shadow: red 10px 10px 10px; } |
最後,我們可以包含多個text-shadow
,寫成逗號分隔的組。陰影效果將從前到後被應用:第一個陰影在上面,其它的在後面。陰影不能覆蓋文字本身。在下面的例子中,紅色的陰影將作用在綠黃色陰影上方。
1 2 3 4 5 |
.example { text-shadow: 10px 10px red, -20px -20px 5px lime; } |
總結
如果你寫 CSS 為生,瞭解如何正確地寫有效的 CSS 屬性值是非常重要的。一旦你理解了不同值之間是怎樣組合疊加的, CSS 的屬性值語法就變得更加容易理解。然後就更容易閱讀各種規則,寫有效的 CSS.
擴充套件閱讀,請檢視以下網站:
- “Value Definition Syntax” in “CSS Values and Units Module Level 3,” W3C
- “CSS Reference,” Mozilla Developer Network
- “How to Read W3C Specs,” J. David Eisenberg, A List Apart
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式