CSS3 中calc()關鍵字+(加)、-(減)運算符為何必須加空格?

that the grammar requires spaces around binary 『+』 and 『-』 operators. The 『*』 and 『/』 operators do not require spaces.

CSS Values and Units Module Level 3

中文規範:http://www.w3.org/html/ig/zh/wiki/Css3-values#.E8.AF.AD.E6.B3.95


大體上是為了消除歧義,深入的話,是由於解析器的標識的歷史定義造成的,所以也算一個歷史問題。

可以看看css的語法和基礎數據類型:Syntax and basic data types

核心語法是

stylesheet : [ CDO | CDC | S | statement ]*;
statement : ruleset | at-rule;
at-rule : ATKEYWORD S* any* [ block | ";" S* ];
block : "{" S* [ any | block | ATKEYWORD S* | ";" S* ]* "}" S*;
ruleset : selector? "{" S* declaration? [ ";" S* declaration? ]* "}" S*;
selector : any+;
declaration : property S* ":" S* value;
property : IDENT;
value : [ any | block | ATKEYWORD S* ]+;
any : [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
| DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
| DASHMATCH | ":" | FUNCTION S* [any|unused]* ")"
| "(" S* [any|unused]* ")" | "[" S* [any|unused]* "]"
] S*;
unused : block | ATKEYWORD S* | ";" S* | CDO S* | CDC S*;

然後看值,再看DIMENSION,再翻一下DIMENSION定義:

DIMENSION {num}{ident}

再看{ident}

ident [-]?{nmstart}{nmchar}*

nmstart [_a-z]|{nonascii}|{escape}

nmchar [_a-z0-9-]|{nonascii}|{escape}

所以calc(20px-10px)會有歧義,在解析器看來,是值20以及未知單位px-10px。而乘號和除號就沒有這個問題,所以有沒有空格都是可以的。

其實覺得加減號表示正負也完全說的通,甚至非常方便記憶。比如 100%/2 - 2*2em 看起來就挺好。

規定加減號有空格應該也是權衡之舉吧,至少最後的結果不是很混淆。


純粹的防止歧義。

比如 calc(20em-10px) ,會被解析為 20 和 em-10px 單位(當然不存在這單位,所以就fail了)。

[2013年9月12日更新]

光單位解析還不夠說明為什麼不允許 20em+10px,或者 20em -10px。所以還有正負號的問題。這兩者會被解析為等同於 20em 10px 和 20em -10px 這樣兩個length,比如可以作為 padding 等的取值。(注意:CSS 2.1的grammar里有bug,「num」沒有前導正負號,但在errata里更正了。)

單純從兼容性的角度來說,calc支持不帶有空格的加減號理論上沒有問題,calc本來就擴展了grammar,對於不支持calc的css parser來說,會把calc解析為function,而其中的token就算解析錯誤也不會有什麼問題(因為本來就不支持)。

但是這樣做會造成CSS核心語法的變更,或者導致calc的語法變成特例。對於parser實現來說,也導致不能使用最常見的lex scanner的方式(當然,一定要乾的話,可以把calc中解析錯誤的token拼起來重新parse——不過聽上去就dirty得要死)。所以無論從spec還是implementation的角度,都不會這樣做。簡單的加空格可以保持原來的tokenizer不變(+-號會解析為DELIM)。

以上。


= =。 當初沒有覆蓋到,有人用開了就很糾結了。


猜測是因為+和-兩個符號在現有的標準中用的已經比較多了,比如background-color,p + p

而強制格式可以加快瀏覽器的解析速度?


防止歧義。 "+", "-" 可以代表正負


推薦閱讀:

移動端布局,div按比例布局,寬度為百分比,但又想讓高度和寬度一樣,即讓div為正方形,怎麼做布局呢?
CSS animation 與 CSS transition 有何區別?
用css能實現一個圓等分12份的樣子嗎?
學不會 CSS?

TAG:前端開發 | CSS | CSS3 |