Web 标准是友是敌?
原文出处:http://www.w3cplus.com/css3/css-secrets/web-standards-friend-or-foe.html
标准化流程
与普通大众的理解所不同的是,W3C(World Wide Web Consortium,万维网联盟)实际上并不制定标准。对于 W3C 旗下的各个工作组(Working Groups, WG)来说,W3C 更像是一个论坛,聚集各种兴趣团体并让他们为某个标准而努力。当然,W3C 并不只是作为整个论坛的观察者:它制定整个论坛的基本规则并观察标准制定的整个流程。在撰写本书的时候,CSS WG 已经拥有了 98 个成员,其详细组成如下:
- 86 名成员来自 W3C 的会员公司(88%)
- 7 名受邀专家(7%)
- 5 名 W3C 的全职员工(5%)
你可能已经注意到了,WG 的主要成员(88%)都来自 W3C 的会员公司。这些会员公司,包括了浏览器厂商、流行站点的维护商、研究机构和其他相关的常用技术公司,他们会因为 Web 标准化的流行而获益匪浅。W3C 的会员年费支撑了 W3C 基金会的主要开销,所以联盟可以免费、开源的分发它的各类标准和规范——这与一些需要缴纳授权费的标准化机构不同。
受邀专家是被邀请加入标准化制定流程的 Web 开发者,致力于解决规范制定初期调试时出现的连续性故障——他们往往具有非常深厚的技术背景。
最后,但非次要的是,W3C 还拥有一批为联盟工作的全职员工,他们的主要工作就是协调、促进 WG 和 W3C 之间的联络。
在 Web 开发者中一直有个普遍性的错误观念,认为 W3C 在上层制定了开发标准,然后各种浏览器无论是否愿意接受相关的标准,都必须去遵循和实践。实际上,这种观念跟现实相去甚远:对于接受哪些方面的标准,浏览器厂商比 W3C 更有话语权 —— 上面列出的数字就说明了这个问题。
另一个与普通大众的理解所不同的是:标准不是凭空捏造的,制定标准也不是闭门造车。CSS WG 所有的提交都是透明的,所有的交流都是对公众开放的,欢迎审查和参与到相关项目钟来:
- 大部分的交流都记录在它的邮件列表 www-style 中。www-style 是公开存档的,任何人都可以参与到其中。
- 然后,还有一个时长为一小时的 每周电话会议(weekly telcon)。它并不对 WG 成员之外的公众开放,但相关内容会被记录在 the W3C's IRC server 的 #css 板块中。几天后,这些记录会被清除,然后发布到邮件刘表中。
- 最后,还有一个季度性的面对面会议(quarterly face-to-face meetings),会议内容也会像电话会议一样被记录。如果获得 WG 主席们的同意,那么也可以旁听该会议。
上述所有的内容都只是 W3C 流程中与决策相关的一部分。不过,具体负责编写标准或规范的人,是规范编辑(Spec Editos)。规范编辑可能是来自 W3C 的全职员工、浏览器开发者、受邀专家,也可能是来自 W3C 会员公司的全职员工——这些员工由相关公司支付薪水,用以加快推动标准的制定和实施,从而获得公共利益。
每一份规范从诞生到成熟都要经历多个阶段:
- 编辑草案(Editor's Draft, ED):在规范的第一个阶段,它的内容会比较混乱,只是规范编辑(Spac Editor)整理收集来的各种想法。对于处于这一阶段的规范,不附加任何必要条件,也不保证会被 WG 批准。此外,这也是修改版的第一个阶段:所有的修改内容首先要经过 ED,然后才能被发布。
- 第一次公开工作草案(First Public Working Draft, FPWD):在这一阶段将会发布规范的第一个公开版本,此时往往认为规范可以接受来自 WG 的公开反馈了。
- 工作草案(Working Draft, WD):在第一次公开工作草案发布之后还会有数个工作草案(WDs),新的工作草案会整合来自 WG 和其他更宽泛社区的反馈,进行增量优化。在这一阶段往往会出现第一个实现,但该实现并不是没有经历实验测试的低级版本。
- 候选推荐标准(Candidate Recommendation, CR):该阶段的规范会被看做是相对稳定的版本,接着就会对它进行实现和测试。任何一个规范都不能在没有完整测试的情况下通过该阶段,而且至少要有两个独立的实现。
- 建议推荐标准(Proposed Recommendation, PR):该阶段是 W3C 会员公司对规范发表异议的最后时机。这种异议很少发生,所以推动该阶段的规范进入最终阶段就只是时间的问题了。
- 推荐标准(Recommendation, REC): W3C 规范的最后一个阶段。
WG 成员中的一到两位会成为 WG 主席。主席负责组织会议、协调电话、把握进度,基本上是总揽全局。担任主席一角是非常消耗时间和精力的事情,他们常常被形容为在放牧一群猫。当然,参与制定标准的每一个人都知道这种比较是没有实际意义的:毕竟放牧一群猫事实上要容易的多。
想要了解更多信息?Elika Etemad 编写了一系列精彩的文章,详细介绍了 CSS WG 的运作方式。强烈建议阅读一下。
CSS3,CSS4 和其他的神奇特征
由 Håkon Wium Lie 和 Bert Bos 发布于 1996 年的 CSS 1 是一份非常简略的规范。它内容短小,以至于可以直接放在一个简单的 HTML 页面中,只需大约 64 张 A4 纸就可以打印出所有的内容。
发布于 1998 年的 CSS 2,其内容定义地更加严格,也包含了更多强大的特性,而且还吸纳了两个重要的规范编辑: Chris Lilley 和 Ian Jacobs。此时,它的内容量已经增长到了需要 480 页打印纸才能完全打印出来,几乎不可能被人类完全记忆。
在 CSS 2 之后,CSS WG 认识到了 CSS 的内容量太大,以至于不能将其归纳到一个简单的规范中。这不只让规范变得难以阅读和编辑,也阻碍了 CSS 的进一步发展。任何一个规范想要成为推荐标准,那么它的每一个标准至少需要拥有两个独立的实现并通过严格的测试。显然,这是不切实际的。因此,为了推动 CSS 的发展,CSS 被分隔成了多个模块,每个模块都有自己独立的版本。那些计划出现在 CSS2.1 中的特性因此拥有了一个 Level 3 的编号,比如下面的这些模块:
- CSS Syntax
- CSS Cascading and Inheritance
- CSS Color
- Selectors
- CSS Backgrounds & Borders
- CSS Values and Units
- CSS Text
- CSS Text Decoration
- CSS Fonts
- CSS Basic User Interface
不过,模块化这一新概念是从 Level 1 开始的,比如下面的这些示例:
- CSS Transforms
- Compositing and Blending
- Filter Effects
- CSS Masking
- CSS Flexible Box Layout
- CSS Grid Layout
虽然 “CSS3” 这个词很流行,但实际上并没有类似 CSS 2.1 以及之前版本那样完整的规范。相反,大多数作者只是粗略地引用了一些 Level 3 和 Level 1 的规范。虽然对于 “CSS3” 在作者中有一个共识性的规范范围,但因为过去几年 CSS 模块发展地非常不均衡,所有越来越难用类似 CSS3、CSS4 等术语来定义一个一致性的术语了。
浏览器前缀的冰火两重天
在标准的开发过程中,一直有一个“第二十二条军规”(源自美国作家约瑟夫·海勒的著作《第22条军规》,引申为荒唐的事情):标准制定小组需要根据开发者的需求创建规范。然而,开发者通常没兴趣去测试那些不会应用到产品中的特性。当实验性特性被广泛用于线上产品中时,WG 被迫跟进相关的技术,避免对现有网站的破坏。显而易见,开发者不提前测试相关标准,导致了后期开发受制于历史因素。
过去几年,业界提出了许多种方案来解决这个问题,但都不够完美。普遍受人厌恶的浏览器前缀就是其中一种方案。该方案的具体做法是,对于浏览器中的实验性特性(甚至是专有特性),提供一种附加浏览器前缀名的命名方案。最常见的前缀就是 Firefox 的 -moz
,IE 的 -ms-
,Opera 的 -o-
以及 Safari 和 Chrome 的 -webkit-
。开发者可以毫无限制地使用前缀命名方式调用测试新特性,然后将使用信息反馈给 WG——WG 获得反馈之后可以进一步测试,直至完善。因此,即使在最终的标准化规范中相关特性拥有了不同的名字(没有前缀),也不会与现有的属性(有前缀)相冲突。
听起来还不错,是吧?如你所知,现实与理想总是有差距的。使用具有浏览器前缀的实验性特性让开发者认识到,创建页面特效原来可以这么简单,以至于他们开始在任何地方使用这些特性。使用具有浏览器前缀的属性成为了 CSS 的一种流行趋势:CSS 的教程里用这些属性、StackOverflow 的回答里用这些属性……很快,每一个独立的 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! 和 pleeease 的网站,可以在你粘帖未加浏览器前缀的属性后,返回给你一个添加了所有可用浏览器前缀的属性。此类应用是最早一批尝试自动补全浏览器前缀的先驱,但是随着其他方案的崛起,该方案显得越来越笨拙,已经不再那么流行了。
- Autoprefixer 通过使用 Can I Use... 的数据库,更智能地判断属性应该添加哪些浏览器前缀,并且能像预处理器一样在本地进行编译和执行。
- 我个人开发的 -prefix-free 可以直接在浏览器本地进行特征检测,从而判断所需的浏览器前缀。这样做的好处是很少需要更新该工具,它从浏览器本地环境获取所需的数据,包括必须的属性列表。
- 类似 LESS 和 Sass 的预处理器虽然没有提供任何直接的浏览器前缀工具,但是有很多开发者为常用的属性创建了混合宏,目前也有几个流行的混合宏库。
由于开发者使用无前缀属性保证代码在未来的可用性,所以基本不可能改变这种编程习惯。基本上,我们只能使用早期不完善的规范来做开发,实际使用过程中可以改变的地方极其有限。不用多长时间,每个人都会认识到浏览器前缀就是个悲剧。
近些日子,新的实验性属性已经很少使用浏览器前缀了。相反的是,要想使用实验性属性就需要在浏览器设置中开启相关选项,因为开发者不能告诉用户开启相关选项来浏览页面,所以这种方法可以有效防止开发者将这些属性应用到线上环境中。当然,这样做的后果就是很少有开发者会把玩这些实验性属性。但是,我们还是能够获得足够的反馈——可以肯定的说,相比较使用浏览器前缀的方案,这种反馈的质量更高。不过,浏览器前缀的困扰还会存在很长时间。
更多建议: