01|人人都在喊 CSS3,可谁也说不清 CSS3 到底是什么

Acid2、Acid3 把浏览器厂商抽得不轻之后,前端圈迎来了一段很热闹的日子。

新东西开始一波接一波往外冒:

圆角、阴影、渐变、变形、过渡、动画、多列、弹性布局……

到处都在喊一个词:

CSS3。

问题是,这个词从一开始就带着一点虚。

因为 CSS3 从来不是一个像 CSS1、CSS2 那样完整打包、统一发售的大版本。

W3C 后来自己都专门写文解释过:CSS 从 Level 2 之后就改成了模块化路线。 简单说,就是不再试图写一本巨厚总谱,而是把 SelectorsBackgrounds and BordersTransformsFonts 这些内容拆成一份份小规范,各写各的,各走各的进度。

这么做的原因,其实第三篇已经埋过伏笔了。

大家都被 CSS2 那种“什么都想管,结果什么都落不稳”的经历吓怕了。

于是 CSS 工作组做了一个很务实的决定:

别再整包发货了,能成熟一块,就先放一块出来。

这是工程上非常理性的选择。

可一旦到了开发者世界,事情就开始变得喜感。

因为大家嘴里还在说“CSS3 来了”,实际面对的却是一锅有的模块半熟,有的模块刚下锅,有的模块连锅盖都没掀开的大杂烩。

从这一刻起,前端开始进入一个很奇妙的阶段:

名义上在学同一门技术,实际上每个人学到的可能都不是同一个版本。


02|模块化救了规范,也害苦了叙事

模块化本身没错。

站在 W3C 的角度,它简直是不得不走的一步。Selectors 可以先推进,Backgrounds and Borders 可以先稳定,Grid 这种难啃的骨头可以晚点来,彼此不用捆死在同一辆车上。

这套方法后来甚至被总结成了一种明确的工作思路。你去看 CSS Working Group 关于模块与快照的说明,会看到一句非常核心的话:CSS 之后的“级别”不再是整门语言统一升级,而是各模块各自升级。

工程师听了点头。

市场和媒体却开始发懵。

因为他们最爱的问题永远是:

“所以,CSS3 到底什么时候发布?”

这个问题,W3C 根本没法正面回答。

不是不想答,是没有那个时刻。

于是接下来很多年里,出现了一种很荒诞的景象:

规范世界在说:“没有单一的 CSS3。”

教程世界在说:“今天教你十个 CSS3 炫酷技巧。”

营销世界在说:“我们的浏览器全面支持 CSS3。”

而开发者夹在中间,只能一边点头,一边打开兼容性表格,心里嘀咕:

“你说的这个 CSS3,到底指哪一块?”

这还只是第一层混乱。

真正让前端开始像扫雷的,是第二层。


03|前缀本来是安全带,后来变成了绊马索

-webkit--moz--ms--o-

今天的前端看到这些前缀,大多会想起老旧代码和兼容地狱。可它们刚出现时,初衷并不坏。

厂商前缀本来的意思很简单:

“这个特性我先试着做,但还不保证最后标准就长这样,所以先别把正式名字占了。”

这是一个很典型的工程师式妥协。既想让新能力早点出来给大家试,又怕未来规范一改,生产代码全炸。于是先加个自家前缀,意思是:实验品,谨慎食用。

这个思路在纸面上很体面。

可一进生产环境,人类就开始照旧干人类最擅长的事:

明知是实验品,偏要拿去正式上线。

于是教程开始写:

-webkit-border-radius: 8px;

作者们写着写着就懒了,只写一个最常见的;项目赶着上线,也懒得补全;浏览器厂商一看,站点都在用,只好继续兼容。

到这一步,前缀已经不再是“实验警示牌”,而更像一种奇怪的行话:

谁市场份额大,谁的实验语法就更像事实标准。

这件事后面会炸。

而且会炸得非常难看。


04|Flexbox:一代前端的考古现场

如果你想知道那几年 CSS3 到底有多乱,最好的样本不是别的,就是 Flexbox

它的历史简直像三版不同剧本硬拍成一部连续剧。

2009 年 7 月 23 日,第一份公开的 Flexbox 工作草案出来了。那时候的写法还不是 display: flex,而是 display: box,搭配一堆 box-* 属性,比如 box-flexbox-packbox-orient

后来规范又改了一轮,进入一种很尴尬的中间形态,写法开始变成 display: flexbox

再后来,才慢慢长成今天大家熟悉的:

display: flex;

站在规范编辑那边,这完全说得过去。早期设计不满意,算法要重做,语义要收紧,当然得改。

可站在开发者这边,体验就非常魔幻。

你搜到一篇 2010 年的教程,写的是一套。

你搜到一篇 2011 年的文章,写的是另一套。

你看 2012 年的示例,又是一套。

三篇都说自己在教 Flexbox

这时候你终于会明白,为什么那几年很多前端打开博客第一反应不是“我学到了”,而是:

“等一下,这篇文章写的是哪朝哪代的 Flexbox?”

这就是前缀和模块化联手制造的经典事故。

浏览器为了抢跑,先实现一版。

规范为了修正,再改一版。

教程为了蹭热度,立刻把第一版写进生产。

等第二版出来时,全世界都在帮第一版收尸。


05|2012:前缀终于把自己养成了危机

前缀问题真正大爆炸,是 2012 年

这场戏的背景很简单:移动端 WebKit 当时势头太猛。Safari、Chrome、Android 浏览器,一路把 -webkit- 前缀送成了网页世界最常见的那一个。

结果就是,很多站点和教程开始只写 -webkit-

写着写着,事情就变味了。

不是“某个实验特性先在 WebKit 里可用”。

而是“你不是 WebKit,你看起来就像不支持这个 Web”。

这已经不是语法问题了,是生态绑架。

2012 年 2 月,CSS Working Group 在巴黎面对面会议和后续电话会上,专门讨论了这件事。W3C 那篇后来题目长得吓人的官方博客总结,第一句就把问题摊开了:移动端 WebKit 的垄断压力,已经逼得其他引擎开始考虑要不要去实现 -webkit- 前缀。

这话的荒唐之处,今天看依然很清楚。

本来前缀是为了避免各家实验实现互相撞车。

结果走到最后,大家居然在认真讨论:

“要不我们也支持竞争对手的实验前缀吧,不然用户会以为我们不行。”

这和当年 IE 私货把别人逼得跟着兼容,有一种非常难堪的历史既视感。

所以当时很多人会说:开放 Web 差点又走回 IE6 的老路。

这不是夸张。

因为逻辑真的一模一样:

谁份额大,谁的非标准写法就开始像标准。


06|这一回,连 W3C 自己都急了

前缀危机最有意思的地方,是它不再只是社区在骂。

连 CSSWG 自己都急了。

那篇 2012-02-19 的官方博客总结里,口气并不轻松。它明确说,这个话题争得很激烈,各方不但意见不一样,连彼此的立场细节都还没完全消化清楚。博客还提到:Mozilla、Opera、Microsoft 至少在“确实出了大问题”这件事上是一致的。

后面的讨论方案也很能说明当时的乱局:

  • 要不要给某些特性提速
  • 要不要更早去掉前缀
  • 要不要同时保留前缀和无前缀写法
  • 要不要把别家的前缀当成 alias 兼容掉

你仔细品一下,会发现这已经不是“如何设计一个新属性”了。

这是在收拾一场已经蔓延到生产环境的事故。

而事故的元凶,并不神秘:

教程图省事,作者图省事,浏览器图抢跑,规范图渐进。每一方都只偷了一点懒,最后整条生态一起埋单。

到了 2012 年 8 月,CSSWG 又专门讨论 experimental features policy,试图把前缀这件事重新管起来,至少别再让“实验中”直接等于“线上默认写法”。

这一步来得很晚,但总算来了。


07|所以那几年为什么前端像在扫雷?

现在把这些线重新拎一遍,答案就很清楚了。

不是前端突然变笨了。

也不是 CSS3 天生就邪门。

而是那几年里,几股力量同时在往不同方向拉:

  • 规范为了避免 CSS2 重演,改成模块化
  • 厂商为了抢新能力,靠前缀先上
  • 教程和博客为了追热点,把实验语法写成“今天就能用”
  • 市场又把这一切统称成一个看似清楚、实际很糊的词:CSS3

最后落到开发者手里,就变成了一块大型雷区。

你看到一个新特性,很兴奋。

然后你会问四个问题:

哪版规范?哪家实现?要不要前缀?这篇教程是不是已经过时了?

这就是那一代前端的日常。

所以第五篇真正想讲的,不是“CSS3 有多酷”,而是:

为什么一门看起来越成功、越热闹的技术,反而会在最红的时候把使用者逼得最狼狈。


如果你只记一句,那就记这句:

CSS3 最混乱的时候,不是因为它不流行,而正是因为它太流行了。


编者注(事实核对)CSS Level 2 之后采用模块化路线,见 W3C 关于 modules/snapshots 的说明、CSS Snapshot 2007 及相关历史文章;“没有单一 CSS3 发布时刻”的说法可由这些材料与 Bert Bos 关于 “CSS X” 的博客互证。厂商前缀 的背景与 2012 -webkit- 危机,主要据 CSSWG Wiki: Vendor Prefixes2012-02-19 CSS WG Blog 及同期报道。文中关于 Flexbox 三阶段语法(display: box / display: flexbox / display: flex)的概括,依据 2009 W3C Working Draft 及后来的历史整理与兼容性回顾。将前缀问题概括为“安全带变绊马索”,属写作性比喻,不是规范原文表述。


关键人物速览

  • Bert Bos:后期负责解释“CSS 为什么不再按整包版本升级”的关键历史叙述者之一。你今天对“没有单一 CSS3”这件事的理解,很多都得从他的说明开始。
  • Elika Etemad(fantasai):CSSWG 长期核心编辑与解释者。关于模块化为什么会演变成今天这样,她的文章是理解这段历史的重要入口。
  • Tab Atkins Jr.:后期很多 CSS 模块的重要编辑,尤其在 Flexbox、Grid 等路线里存在感很强。第五篇里那种“规范不断重写”的感觉,和他这代编辑风格关系很大。
  • Daniel Glazman:在模块化和前缀混乱逐步失控时,既是工作组内部角色,也是后来危机篇里的公开发声者。

参考与延伸阅读

  1. W3C:Levels, snapshots, modules…
    https://www.w3.org/Style/2011/CSS-process.en.html

  2. fantasai:CSS WG — Modularization
    https://fantasai.inkedblade.net/weblog/2011/inside-csswg/modules

  3. W3C:CSS Snapshot 2007(Beijing)
    http://www.w3.org/TR/css-beijing/

  4. Bert Bos:‘CSS X’
    https://www.w3.org/blog/2020/css-x/

  5. CSSWG Wiki:Vendor Prefixes
    https://wiki.csswg.org/spec/vendor-prefixes

  6. CSS WG Blog:-webkit- Discussions(2012-02-19)
    https://www.w3.org/blog/CSS/2012/02/19/resolutions-24/

  7. CSS WG Blog:Experimental Features Policy(2012-08-30)
    https://www.w3.org/blog/CSS/2012/08/30/resolutions-53/

  8. Flexbox 2009 Working Draft
    https://www.w3.org/TR/2009/WD-css3-flexbox-20090723

  9. CSS-Tricks:Old Flexbox and New Flexbox
    https://css-tricks.com/old-flexbox-and-new-flexbox/

  10. MDN:Backwards compatibility of Flexbox
    https://mdn2.netlify.app/en-us/docs/web/css/css_flexible_box_layout/backwards_compatibility_of_flexbox/


下篇预告:2012 年前缀危机,差点把开放 Web 拖回 IE6 时代。