日期:2014-05-17  浏览次数:23068 次

【分享】说说标准——CSS的错误解析规则
我说我的眼里只有你 —— 景岗山

用这句歌词来形容CSS的错误解析规则,我觉得再合适不过。CSS的错误解析规则的眼里只有CSS标准,对其他的错误语法,大都采取直接忽略的态度,太**忠心了(此处省略三字)。

CSS跟我们所认识的其他语言,例如 JavaScript,一样,也有自己的语法,它适用于任何版本的CSS,描述了CSS的核心句法(syntax)、关键字、厂商扩展、可用字符集、规则集合、声明块、选择器、特性以及注释等所有CSS的构成部分。是组成CSS的根本。详细的资料,请参见:W3C CSS2.1中的 4.1 Syntax。

标准如同法律,有没有是一回事,切身相关的人执不执行有是另一回事。不同的是,法律带有强制性,标准就带有妥协性。你按照标准写,则可以正常的运作,否则,标准会根据它的错误解析规则,处理你的代码,大多数时候,是丢弃错误部分。不可能说你CSS写错了,出了大错就要毙掉,小错就要改造。如果是那样,估计没人敢碰了……

那么,CSS2.1中到底是如何处理错误的呢?
CSS语法规定了CSS的写法,但是开发人员还是可能写出不合CSS语法的代码,这时候,浏览器就需要忽略一部分不合法的样式表。
CSS2.1及所有后继版本中,对于任何以破折号、下划线开头的property:value组合和不包含标识符的@-keywords组合,都以忽略的方式处理。
比如:
CSS code
div{ _height: 19px;}
上面存在下划线开头的特性值,按照规则,应该忽略这个声明。
而只有IE6,以及IE7和IE8的兼容模式下会自动修复这个声明,其他浏览器都忽略该声明。
在IE6(Q)(S)/IE7(Q)/IE8(Q)中,最终会解析成:
CSS code
div{ height: 19px;}
补充一句,这就是著名的 IE CSS hack。

为了保证新的属性和值可以被正确添加,但遇到以下情况时,浏览器必须遵循以下的规则:
1. 未知的属性
浏览器必须忽略带有未知属性的声明。
如,
CSS code
p{yes:'good'}
yes不是CSS中已有的属性,所以,应当忽略此声明。
在所有浏览器中,该声明都会被忽略。

2. 不合法的值
浏览器必须忽略带有不合法值的声明。
如,
CSS code
p{height:20}
height的值应该是一个数字后加一个单位构成的值。只有一个数字的值是不合法的。应当忽略。
虽然标准如此,但是这个值在IE/Opera/Firefox/Chrome/Safari的兼容性模式下有效,在它们的标准模式下才会被忽略。可见,兼容性模式下对其做了自动修复。

3. 畸形的声明
当浏览器解析一个声明时,读取它的代码直到这个声明的结束,同时,检查 (), [], {}, "", 和 '' 的匹配规则,并且正确的处理编码,这时候,浏览器必须处理它所遇到的意外出现的标记。 怎样处理?标准没有明确指出。因为针对不同的情况,应该采取不同的处理手段。很多兼容性问题也都是因为标准没说明白造成的!!
如,
CSS code
p{height} /* 丢失了 ”:” 和后面的值,此属性应被忽略 */
({)P{width:100px}   /* 多余的  ({),此行应被忽略*/
这两条声明都是错误的,应该被忽略。
在所有的主流浏览器中,这两个声明都被忽略了。

4. 不可用的@关键字
如:
CSS code
@hello{...}
@hello不是标准中的@关键字。
所有浏览器都会忽略此声明。

5. 样式表的意外结束
浏览器必须自动闭合敞开的结构(如,块,字符串和注解等)

CSS code
@media screen { p:before { content: 'Hello
应该解析为:
CSS code
@media screen { p:before { content: 'Hello' } }
实际上,IE/Opera/Safari/Firefox/Chrome都没有自动的修正。注意,IE8才开始支持@media screen。
稍微修改一下:
CSS code
@media screen { p:before { content: 'Hello'
注意,现在Hello文本后增加了一个单引号。
这时,IE8的标准模式下,以及Firefox/Chrome/Safari/Opera都可以自动的添加未闭合的 "}";IE其他版本和模式下不能修复是因为不支持@media screen。

6. 字符串的意外结束
如,
CSS code
p { color: green; font-family: 'Courier New Times color: red; color: red; }
应被解析为:
CSS code
p { color: green; color: red; }