CSS语法简单学习

有这个博文的原因是,最近想做一个CSS的工具,至于工具的作用,先暂时不公开了,有兴趣的朋友可以邮件单独和我联系讨论下。为了这个工具,首先需要有一个CSS解析器,我称之为CSSParser,同时这个解释器和普通的基于Lex的词法分解+LR1的语法分析不同,他并不按标准给定的语法进行严格的检查,而仅仅分解出CSS中的各个元素。

为此,第一步自然是对CSS的语法有一个简单的了解,无论我的解释器是否按标准的语法进行解释,至少CSS语言的组成部分是必须明确的。此文也谨作总结之用。

整体组成

在CSS中,顶层元素被称为Rule,而CSS中的Rule又分为2类:CSSStyleRule和CSSAtKeywordRule。

CSSStyleRule是最基本的,即我们最常见的,由选择器+属性+值组成的部分,以下就是一个简单的示例:

#nav>li~li {
    float: left;
    margin-left: 7px;
    padding-left: 7px;
    border-left: 1px solid blue;
}

而CSSAtKeywordRule则是另一类,这个名词是我起的,事实上在w3c给出的JAVA API中,他被分成很多个类:

一目了然,所谓CSSAtKeywordRule,就是以@起始的那一批关键字类型的规则,CSS3一共就规定了以上6个,不多不少。

除了CSSStyleRule和CSSAtKeywordRule以外的,所有不能正确解释的,统统被称为CSSUnknownRule,这个自然没有太大的意义,就不详细说明。

元素顺序

CSS对元素的顺序没有太大的要求,多数位置可以出现在任意位置,出现任意的次数,除了2个特例:

  • @charset只能出现在文档头部,前面不能有任何字符。
  • @import必须出现在@charset(如果有的话)之后,其他规则之前,当然可以有多个。
  • @import不能出现在大括号之间(语法上称为block内部)。

因此一个CSS文档的顺序基本是这样的:

  1. @charset声明。
  2. @import引入其他样式。
  3. 其他规则任意次序任意次数依次叠放。

CSSAtKeywordRule

着重讲解一下几个CSSAtKeywordRule的定义:

@font-face

嵌入字体,在CSS3被大肆宣传的今日,开发者应该蛮熟悉了,用src指定地址,用font-family指定名称,如:

@font-face {
    font-family: "Title Only";
    src: url(xxx.ttf) format("truetype");
}

具体可以看看这里,有很详细的介绍。

@media

指定样式作用的媒体类型,如screen代表屏幕、projection代表投影仪等,需要注意的是@media是一个可嵌套规则的规则,即他本身就带有类似CSS文档的效果,内部可以定义其他的规则,因此以下代码是合理的:

@media projection {
    /* 长得就像一份完整的CSS文档 */
    body {
        width: 960px;
        background-color: #efefef;
    }
}

@page

根据标准,是给Paged Media使用的,在探寻过程中,发现基本可以认为是给打印机用的特定样式规则,其内部使用一些比较特殊的属性,以下是个简单的列表:

  • size - 指定页面大小,或者A4、B5之类的预设大小,也可以是landscape或portrait指定打印方向。
  • margin - 已经不是指元素的边距了,指定打印时的页边距。
  • backgroundborderpaddingcolorfonttext等都指打印时的效果。

CSSStyleRule

然后是重头戏CSSStyleRule,CSS中真正起作用的还不就是那些属性+值的样式么。一个CSSStyleRule的组成如下:

Selector { CSSStyleDeclaration* }  

关于选择器即Selector,CSS3标准的相关章节中有详细的介绍,本文不考虑这方面的展开了。

CSSStyleDeclaration就是一个键值对,他的组成如下:

property : value;  

需要注意的是分号不能省略,CSS可不像javascript一样有自动分号补全功能,事实上在CSS中不存在换行符的特殊处理,换行符会被当空格同等对待,所以下面这样的样式:

div {  
    background: red
    padding: 3px;
}

会等同于:

div {  
    background: red padding: 3px;
}

padding:3px分别被认为是属性background的值的一部分,根据CSS3的定义,分别对应background-imagebackground-position属性,形成非法的样式值。因此分号是CSS的同一个CSSStyleRule内多个并列样式间的唯一的分隔符,不可省略。唯独一个CSSStyleRule中的最后一个Declaration的分号可以省略,因为其后其父规则已经结束了。

值类型

CSS也是有数据类型的,大致有这么几类:

  • 数字,即普通的数字,可以带负号,可以有小数。
  • 长度,有3个相对单位,分别是em、ex和px;5个绝对单位,分别是in、cm、mm、pt、pc。
  • 百分比,数字后跟一个百分号就行了。
  • URL/URI,使用一个叫url的函数来定义,如url(http://www.google.com)。
  • 计数器:大概有人用过,但用得不广泛,用来给ol标序号的时候用得比较多吧。
  • 颜色:CSS2规定的颜色是RGB色,到了CSS3变成RGBA,颜色的表示形式有#rgb[a]#rrggbb[aa]rgb[a](r, g, b, [a])这么几种,注意#ff009不是一个合法的颜色,因为即不符合3|4位,也不符合2*(3|4)位。
  • 角度,有3个单位,分别是deg、grad、rad。
  • 时间,单位有ms和s。
  • 频度,真没见用过,单位有Hz和kHz。
  • 字符串,使用配对的双引号或单引号包含,内部的引号要转义,这是基本常识。CSS支持多行字符串,\后紧跟换行即可。不过要注意的是,CSS中的多行字符串里的换行符好像会被忽略掉,真正要用到换行符的时候,使用\A来代表一个换行符。

总结

以下是一般性的、以阅读为目的的总结,并不是对标准语法的描述:

CSS文档的组成:

CSSDocument :  
    CSSAtCharsetRule? + 
    CSSAtImportRule* + 
    [CSSStyleRule | CSSAtMediaRule | CSSAtPageRule]*

CSSStyleRule的组成:

CSSStyleRule :  
    Selector +
    { +
    CSSDeclaration* +
    }

CSSDeclaration的组成:

CSSDeclaration :  
    Property + 
    : + 
    Value + 
    ;

CSSAtMediaRule的组成:

CSSAtMediaRule :  
    @media +
    CSSMediaType+ +
    { + 
    [CSSStyleRule | CSSAtMediaRule | CSSAtPageRule]* +
    }