2026-05-16浏览器Web标准WebKit前端架构

浏览器是如何"特殊照顾"大网站的——WebKit Quirks 深度解析

当你打开 Safari 访问 Facebook 看视频时,你有没有想过:为什么视频不会像预期那样暂停?为什么播放器行为和 Chrome 不太一样?

biluo·5247 words

前言

当你打开 Safari 访问 Facebook 看视频时,你有没有想过:为什么视频不会像预期那样暂停?为什么播放器行为和 Chrome 不太一样?

答案藏在 WebKit 的源代码里。一个叫 Quirks.cpp 的文件,里面全是这样的代码:

`cpp

// Facebook, X (twitter), and Reddit will naively pause a

// that has scrolled out of the viewport, regardless of whether that element

// is currently in PiP mode.

`

这行注释翻译过来就是:Facebook、Twitter、Reddit 会粗暴地在视频滚出视口时暂停它,不管视频是否在画中画模式。所以 WebKit 引擎检测到你在这些域名,就偷偷改变视频行为,让这些"错误代码"也能正常工作。

这不只是修复 bug — 这是现代浏览器工程的核心矛盾。

一、浏览器为什么要有域名黑名单?

传统观点认为:W3C 标准是规范,浏览器实现规范,开发者遵循规范,大家相安无事。

现实完全不同。

1.1 真实案例:SeatGuru 的修复

看 WebKit Quirks.cpp 里的这行注释:

`cpp

// FIXME: Remove this quirk if seatguru decides to adjust their site.

`

SeatGuru 是一个航班座位选择的网站。他们有某个渲染问题,WebKit 工程师尝试联系对方修复,但对方没有回应。于是 WebKit 直接在浏览器里写了一个判断:if (domain == 'seatguru.com') apply_this_workaround()

这个修复shipping到了每一台 iOS 设备上。所有 Safari 用户都受益于这个没有人知道的修复。只有看源代码你才能发现自己的网站被"特殊对待"了。

1.2 经济学解释:为什么不走正规流程?

想象你是 WebKit 团队,你发现 Netflix 在 Safari 上完全无法播放视频。

走正规流程:联系 Netflix 团队 → 等对方确认 → 等排期 → 等上线。几个月过去了,用户体验依然很差。

走捷径:写一个 if (domain == 'netflix.com') spoof_user_agent('Chrome'),5 行代码,今天 ship,今天用户就能看 Netflix 了。

所以 Firefox 也做了完全相同的事情。当网站检测 Chrome UA 并给出不同的页面时,Firefox 的策略是:「好吧,既然你非要 Chrome,那我就假装是 Chrome。」

`cpp

auto chromeUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "

"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"_s;

`

Safari 把自己伪装成 Chrome,就为了让某些网站不报错。这听起来荒谬,但这是每天数十亿次页面加载中真实发生的事情。

二、Quirks 文件里到底有什么?

WebKit 的 Quirks.cpp 不是一个小的 workaround 文件——它有数千行,每一行都是一个域名判断。

2.1 真实的 quirk 类型

视频相关

  • Facebook/Reddit/Twitter:视频滚出视口时错误暂停 → 浏览器忽略这个暂停信号
  • Twitch:切换标签页时错误暂停 PiP 视频
  • Instagram Reels:播放时尺寸计算错误

触摸事件

  • Amazon:产品图片放大镜的触摸事件处理不符合标准 → WebKit 专门为 Amazon 改变了触摸到鼠标事件的翻译逻辑

CSS 渲染

  • Zillow:楼层图图片不能居中显示
  • 多个流媒体网站:播放控件的 z-index 计算错误

用户代理欺骗

  • Amazon Video:需要 Chrome UA 才能播放 DRM 内容
  • 多个流媒体服务:明确检测非 Chrome 浏览器并降级体验

2.2 代码结构

一个典型的 quirk 看起来是这样的:

`cpp

// Amazon product image magnification

if (equalIgnoringASCIICase(requestedURL.host(), "www.amazon.com")) {

// When panning on an Amazon product image, we're either touching

// on the #magnifierLens element or its previous sibling.

// Adjust event handling specifically for Amazon's broken implementation.

}

`

这种模式在代码库里重复了数百次。每一个都是:某个大网站写了错误代码 → 浏览器选择修复它而不是让用户受苦。

三、Chrome 的不对称优势

WebKit 的 Quirks 文件和 Firefox 的 about:compat 页面的存在,揭示了一个深刻的不对称:

Chrome 不需要 quirks 文件。

原因不是 Chrome 代码质量更高,而是:

3.1 市场份额即标准

当 Chrome 拥有超过 80% 的浏览器市场份额时,「在 Chrome 上能工作」几乎等同于「在互联网上能工作」。

开发者的开发流程变成了:

1. 在 Chrome 上开发

2. 测试 Chrome

3. 如果在 Safari 上坏了,那是 Safari 的问题

于是 WebKit 和 Gecko 必须追着 Chrome 跑。Chrome 实现了一个非标准行为,开发者开始依赖它,标准委员会最终把它写进了规范,因为「这是事实上的标准」。

HTML5 规范采用「Living Standard」模式,本来是为了解决 IE/Netscape 时代碎片化问题的。结果呢?规范确实跟上了现实,但现实是由 Chrome 定义的。

3.2 反馈循环

`

Chrome 市场份额高

→ 开发者优先适配 Chrome

→ Chrome 行为成为事实标准

→ 非 Chrome 浏览器被迫兼容 Chrome 行为

→ 用户在非 Chrome 浏览器上遇到奇怪问题

→ 换回 Chrome(以为是浏览器的问题)

→ Chrome 市场份额更高

`

这不是阴谋,这是市场自然演化的结果。但结果是:Chrome 设置议程,其他浏览器只能响应。

四、这对前端开发者意味着什么

4.1 你的「正常」可能是赝品

如果你在 Chrome 里开发,测试,发布——你的网站在 Chrome 上「正常工作」,可能不是因为你的代码正确,而是因为 Chrome 的行为恰好符合你的预期。

在其他浏览器上,同样的代码可能产生完全不同的结果。而你不知道的是:那些浏览器可能正在用 quirks 为你买单。

4.2 如何检测你网站是否在 quirks 名单里

Firefox 用户:

1. 地址栏输入 about:compat

2. 滚动到页面底部搜索你的域名

3. 如果找到记录,说明你的网站正在被特殊处理

直接查源码:

  • WebKit: https://github.com/WebKit/WebKit/blob/main/Source/WebCore/page/Quirks.cpp
  • Firefox: https://searchfox.org/firefox-main/source/browser/extensions/webcompat/data/interventions

4.3 正确的开发习惯

不要只在 Chrome 里测试。 定期在 Firefox 和 Safari 里验证你的关键用户流程。特别注意:

  • 视频播放逻辑
  • 表单提交和验证
  • 拖拽和触摸事件
  • 支付和认证流程

如果一个功能只在 Chrome 上正常,问问自己:是 Chrome 做对了,还是我的代码依赖了 Chrome 的错误行为?

五、从 Quirks 到更健康的生态

5.1 规范真的在进步

值得注意的是,现代 HTML/CSS 规范比以前好很多。Canvas、Fetch API、Web Components 这些新标准的实现一致性比十年前高得多。Living Standard 模式至少让规范跟上了实现,而不是反过来。

问题在于:即使规范好了,开发者行为不会一夜之间改变。有数百万行老代码依赖着 Chrome 特定的行为,这些代码会存在很多年。

5.2 减少 quirks 的根本方法

Mozilla 工程师 Katryna Blaettner 在一篇博客里描述了理想流程:

1. 网站报告 bug

2. 浏览器联系网站

3. 网站修复

4. 浏览器移除 quirk

他们真的在执行这个流程——当 FlightAware 最终修复了他们的 CSS transform 代码后,WebKit 删除了针对 FlightAware 的 quirk。但这个过程可能需要数月,而且需要网站方配合。

5.3 我们能做什么

作为前端开发者,我们可以做几件事:

第一,不要假设 Chrome 等于标准。 在开始项目前,检查 Can I Use,了解各浏览器实际支持情况。在 writing 代码时考虑「这在 Firefox 里会怎样」。

第二,给浏览器厂商反馈渠道。 如果你发现网站在非 Chrome 浏览器上行为异常,主动联系那些网站的开发者,而不是期望浏览器来打补丁。

第三,理解 UA 检测的害处。 你的服务器不应该拒绝非 Chrome 的浏览器。检测 UA 是 quirks 产生的重要原因之一——当你检测 UA 并给出不同内容时,你强制浏览器用撒谎来保护用户体验。

六、尾声:正在变长的清单

WebKit Quirks.cpp 的 commit 历史很有趣——最近几个月新增的条目包括:

  • Zillow 楼层图不能居中
  • TikTok 提示「请升级浏览器」(这是一个假的错误提示)
  • Instagram Reels 播放时尺寸跳动
  • Netflix「Episodes and Info」按钮错误关闭弹窗
  • Twitch 切换标签页时暂停 PiP

每一个条目都是:某个顶级网站写了 bug,浏览器选择直接修,而不是让用户受损。

这些修复 Invisibly 让 web 保持了运转,但它们也在强化一个不公平的体系:写错代码的网站不需要修复,因为他们的大用户量会让浏览器来适应他们。

Chrome 的市场份额让它的每一个决定都成为标准。其他人只能追。WebKit 和 Firefox 的 quirks 文件,记录了这个追的过程中的所有妥协。

而你的网站,可能也在这些文件里,只是你不知道而已。

---

*参考资料:*

  • *[WebKit Quirks.cpp](https://github.com/WebKit/WebKit/blob/main/Source/WebCore/page/Quirks.cpp)*
  • *[Mozilla Firefox WebCompat Interventions](https://searchfox.org/firefox-main/source/browser/extensions/webcompat/data/interventions)*
  • *Katryna Blaettner: "[Removing a WebKit quirk for FlightAware](https://www.otsukare.info/2023/01/16/webkit-quirks)")*