第1章 引言
Web标准:是敌还是友
图1-1
“标准就像香肠:最好别去看它们是怎么做出来的。”
——某位匿名的W3C工作组成员
图1-2
CSS工作组的人员结构:
会员公司特邀专家W3C工作人员
标准的制定过程
与大众的理解大相径庭的是,W3C并不“生产”标准。实际上,它扮演的是一个论坛的角色:W3C以工作组的方式,把某项技术的相关各方聚集起来,最终由他们来产出标准。当然,W3C并不只是一个观察者:它设定了整个平台的规则,监督整个进程。但这些技术规范(基本上)并不是由W3C的工作人员编写完成的。
CSS规范通常是由CSS工作组的成员来编写的。在编写本书时,CSS工作组共有98名成员,人员结构如下:
■86名来自W3C会员公司的成员(88%)
■7名特邀专家(笔者有幸在列)(7%)
■5名W3C工作人员(5%)
你可能注意到了,工作组的绝大多数成员(88%)来自W3C会员公司。这些公司(比如浏览器厂商、主流网站、研究机构、常规技术公司等)都是Web标准兴旺发展的直接受益者。它们每年的会费也是W3C的主要资金来源,使得W3C能够免费、开放地发布所有技术规范,而不像其他标准制定组织那样不得不采取收费政策来维持运作。
特邀专家是指那些被邀请参与标准制定的Web开发者。在真正获得这样的殊荣之前,他们需要证明自己在解决难题时能够持续不断地投入,在参与讨论时能够体现出深厚的技术背景。
最后,同样不可忽视的是W3C工作人员。他们才是真正在W3C内工作的人,他们为工作组和W3C之间的交流提供便利。
Web开发者们普遍存在一个误解,以为W3C手握标准、号令天下,而可怜的浏览器厂商们则唯唯诺诺、莫敢不从。这显然不是真相:对于哪些东西该进入标准,浏览器厂商比W3C有更多的发言权,上面列出的人员结构已经证明了这一点。
同样跟大众观念截然相反的是,制定标准并不是闭门造车。CSS工作组坚持透明原则,它内部所有的交流都是公开的,并邀请公众的关注和参与。
■绝大多数的讨论都发生在工作组的邮件列表中:www-style(http://lists.w3.org/Archives/Public/www-style)。这个邮件列表是公开存档的,欢迎任何人的参与。
■每周都会召开一次电话会议,时长一小时。该会议并不向非工作组成员开放,但它会被实时记录在W3C的IRC服务器(http://irc. w3.org/)上的#css频道。这些会议记录会在几天内整理出来,并发布到邮件列表中。
■还有每季度一次的面对面会议,也会以上述方式进行会议记录。在获得工作组主席的许可之后,这类会议也通常会对观察员开放(以旁听的方式)。
所有这些都是W3C进程的一部分,任何决定都是通过这样的方式来产生的。此外,那些真正负责把这些决定写成文字(即编撰规范)的人叫作规范编辑。规范编辑可能是W3C的工作人员、浏览器开发者、相关专业的特邀专家;也可能是会员公司的雇员,他们全职从事此工作,为了共同利益去推进标准。
每项规范从最初启动到最终成熟,都会经过以下阶段。
(1) 编辑草案(ED):这是一项规范的初始阶段,可能非常粗糙,就像是编辑们想法的大杂烩。对这个阶段没有什么要求,也不保证它会被工作组批准。但它也是各个修订版本的必经阶段,每次变更都是先从一个ED中产生的,然后才会发布出来。
(2) 首个公开工作草案(FPWD):一项规范的首个公开发布版本,它应该准备就绪,以接受工作组的公开反馈。
(3) 工作草案(WD):在第一个WD之后,还会有更多的WD出来。这些WD会吸收来自工作组和更广阔的社区的反馈,一版接着一版小幅改进。浏览器的早期实现通常是从这个阶段开始的,厂商基本不太可能对更早阶段的草案提供实验性的支持。
(4) 候选推荐规范(CR):这可以认为是一个相对稳定的版本。此时比较适合实现和测试。一项规范只有具备一套完整的测试套件和两个独立的实现之后,才有可能继续推进到下一阶段。
(5) 提名推荐规范(PR):这是W3C会员公司对这项规范表达反对意见的最后机会。实际上他们很少在这个阶段提出异议,因此每个PR推进到下一阶段(也是最后一个阶段)只是时间问题。
(6) 正式推荐规范(REC):一项W3C技术规范的最终阶段。
工作组中会有一到两位成员担任主席的角色。主席负责组织会议、协调讨论、控制时间,而且要从大局上斡旋整件事情。担任主席是一件耗时费神的工作,经常被比作养一大群猫。当然,所有接触过这项工作的人都知道这个比喻并不恰当——养猫比这要容易多了。
图1-3
主持W3C工作组往往被比作养一大群猫
CSS3、CSS4以及其他传说
CSS 1的规范由Håkon Wium Lie和Bert Bos发表于1996年,它非常短,而且比较简单。它的内容少到用一个HTML页面就足以呈现了,即使用A4纸打印出来也只需要68页。
CSS 2发表于1998年,它的定义更加严格,囊括了更多的功能,而且增加了两名编辑:Chris Lilley和Ian Jacobs。此时,规范的篇幅暴增到了480页打印纸,人们已经无法把它完整地记忆下来了。
在CSS 2之后,CSS工作组意识到这门语言已经变得非常庞大,再也无法把它塞进单个规范中了。这样不仅阅读和编辑极其困难,而且限制了CSS本身的快速发展。别忘了,一项规范如果要推进到最终阶段,其中的每项特性都必须具备两个独立的实现和全面的测试。原先的那种方式已经玩不转了。因此,我们决定跨出一步,将CSS打散到多个不同的规范(模块)中,每个模块都可以独立更新版本。这其中,那些延续CSS 2.1已有特性的模块会升级到3这个版本号。比如以下模块:
■CSS语法(http://w3.org/TR/css-syntax-3)
■CSS层叠与继承(http://w3.org/TR/css-cascade-3)
■CSS颜色(http://w3.org/TR/css3-color)
■选择符(http://w3.org/TR/selectors)
■CSS背景与边框(http://w3.org/TR/css3-background)
■CSS值与单位(http://w3.org/TR/css-values-3)
■CSS文本排版(http://w3.org/TR/css-text-3)
■CSS文本装饰效果(http://w3.org/TR/css-text-decor-3)
■CSS字体(http://w3.org/TR/css3-fonts)
■CSS基本UI特性(http://w3.org/TR/css3-ui)
此外,如果某个模块是前所未有的新概念,那它的版本号将从1开始。比如下面这些:
■CSS变形(http://w3.org/TR/css-transforms-1)
■图像混合效果(http://w3.org/TR/compositing-1)
■滤镜效果(http://w3.org/TR/filter-effects-1)
■CSS遮罩(http://w3.org/TR/css-masking-1)
■CSS伸缩盒布局(http://w3.org/TR/css-flexbox-1)
■CSS网格布局(http://w3.org/TR/css-grid-1)
尽管“CSS3”这个名词非常流行,但它实际上并没有在任何规范中定义过。这一点跟CSS 2.1或更早的CSS 1不一样。真正的情况是,绝大多数编辑在提到这个词时,指的是一个非正式的集合,它包括CSS规范第三版(Level 3)再加上一些版本号还是1的新规范。尽管在哪些规范应该归入CSS3的问题上,编辑们达成了一定的共识,但我们也不得不面对现实:由于CSS的各个模块在近些年里以不同的速度在推进,我们已经越来越难以把这些规范以CSS3、CSS4这样的方式来划分了,而且这样也难以被大众理解和接受。
冰与火之歌:浏览器前缀
在标准的开发过程中,总是有大大的“第22条军规”挡在面前:标准的工作组需要网页开发者这一端的输入,以确保各项规范可以处理真实的开发需求;但是开发者往往没有兴趣尝试那些在生产环境中还不能使用的东西。当实验性的技术被广泛应用到生产时,工作组就被这些技术早期的、实验性的版本捆住手脚了,因为一旦这些技术有变动,那些已经在用这些技术的网站就挂了。显然,这完全否定了让开发者尝试早期标准的好处。
这些年来,为了解决这个难题,许多方案被提了出来,但都不够完美。饱受诟病的浏览器前缀就是其中之一。这个方案是指每个浏览器都可以实现这些实验性的(甚至是私有的、非标准的)特性,但要在名称前面加上自己特有的前缀。最常见的前缀分别是Firefox的-moz-、IE的-ms-、Opera的-o-以及Safari和Chrome的-webkit-。网页开发者可以自由地尝试这些加了前缀的特性,并把试用结果反馈给工作组,而工作组随后会将这些反馈吸收到规范之中,并且逐渐完善该项特性的设计。由于最终标准化的版本会有一个不同的名称(没有前缀),它在实际应用中就不会跟加前缀版本相冲突了。
听起来不错,对吧?但是你可能也猜到了,现实与我们的期望往往有很大的落差。当开发者发现这些实验性的、加了前缀的属性可以轻而易举地实现以前大费周章才能达到的效果时,他们就开始滥用了。这些加了浏览器前缀的属性迅速成为CSS领域的一大潮流。网上的教程会写到它们,Stack Overflow上的问答会提到它们……很快,几乎每个有上进心的CSS开发者都开始争先恐后地使用它们。
不久,网页开发者们就发现,在使用这些神奇的新特性时,如果只写出当下有效的浏览器前缀,就意味着以后要经常回来打补丁:每当又一个浏览器实现了这个新特性时,他们都需要多加一行。跟进各个特性在各个浏览器下是不是要加前缀,光是想想就让人头皮发麻。开发者会怎样应对?那就是先发制人地加上所有可能的浏览器前缀,再把无前缀的版本放在最后,以图一劳永逸。我们最终写出的代码可能就是这样的:
-moz-border-radius:10px; -ms-border-radius:10px; -o-border-radius:10px; -webkit-border-radius:10px; border-radius:10px;
这里面有两条声明是完全多余的:-ms-border-radius和-o-border-radius这两个属性从来没有在任何浏览器中出现过,因为IE和Opera从一开始就是直接实现border-radius这个无前缀版本的。
显然,把每个声明都重复五遍是相当枯燥的,而且很难维护。因此出现某个工具来把这项工作自动化只是个时间问题。
■像CSS3, Please! (http://css3please.com)和pleeease(http://pleee-ase.io/playground.html)这样的网站允许你把无前缀的CSS代码粘贴进去,它们会自动帮你把必要的前缀都加好。这类网站是“前缀危机”所催生出的第一批工具,很快就过气了,因为跟其他方案相比,它们的使用成本太高了。
■Autoprefixer(https://github.com/ai/autoprefixer)采用Can I Use...(http://caniuse.com)的数据库来判断哪些前缀是需要添加的;此外,它是在本地完成编译的,类似预处理器。
■我自己开发的 -prefix-free(http://leaverou.github.io/prefixfree)会在浏览器中进行特性检测,来决定哪些前缀是需要的。它的好处在于几乎不需要更新,因为其所有信息都是用一份属性清单在真实的浏览器环境中跑出来的结果。
■类似 Stylus(http://stylus-lang.com/)、LESS(http://lesscss.org)或Sass(http://sass-lang.com)的预处理器并不自带任何加前缀的方法,但很多人开发过一些能为常用属性加前缀的mixin;社区中也有一些库提供了这类mixin。
由于网页开发者使用无前缀的属性是想确保代码的向前兼容,那么工作组想要修改这些无前缀语法就变得不可能了。我们基本上就跟这些半生不熟的早期规范绑在一起了,只能通过极其有限的途径来修改它们。用不了多久,这个“坑”里的每个人就会意识到,浏览器前缀已是一场史诗般的失败。
最近,浏览器厂商已经很少以前缀的方式来实验性地实现新特性了。取而代之的是,这些实验性特性需要通过配置开关来启用,这可以有效防止开发者在生产环境中使用它们,因为你不能要求用户为了正确地浏览你的网站而去修改浏览器设置。当然,这会导致一个后果:尝试这些实验性特性的开发者会减少;但我们仍然会得到足够多的反馈,甚至是更高质量的反馈(你可能会质疑),同时还避免了浏览器前缀的所有缺点。不过我们还需要很长的时间,才能从浏览器前缀所引发的涟漪效应中解脱出来。