Chrome 中 scrollingElement 的变化

相信大部分前端同学都知道,Webkit 对于页面滚动条位置,没有按照标准处理。以下是一段相关描述,摘自 W3Help

在混杂模式下,由于所有浏览器均使用 document.body.scrollTop 获取页面的垂直滚动条的位置,所以不会出现兼容性问题。而在标准模式下,由于 Chrome 与 Safari 仍然使用 document.body.scrollTop,而对于 document.documentElement.scrollTop 返回为 0。

也就是说对 Webkit 来说,无论是混杂模式还是标准模式,它都认为页面滚动元素是 BODY;而其它浏览器只有在混杂模式下,才会认为页面滚动元素是 BODY,标准模式下则是 HTML

各种 JS 库通常都会抹平不同浏览器及不同模式下的这些差异,统一提供获取或设置 scrollTop / scrollLeft 的接口,所以这个问题往往不会暴露出来。具体的兼容方案很简单,略过不提。但需要注意一点,千万不要使用 UA 检测来解决这个问题,如果针对 UA 包含 webkit 的浏览器统一使用 document.body 那就有问题,后面会讲到原因。

最近我发现了一个诡异的现象:在我的 Chrome 里需要通过 document.documentElement 元素获取页面滚动条位置。原本我以为是 Chrome 修改了实现,保持跟标准一致;但奇怪的是,我的 Chrome Canary 还是老样子,别人跟我版本一致的 Chrome 也还是老样子。

为了彻底搞明白这件事情,我在 Chromium Bug 系统中开始了搜索。很快,我找到一个描述这个问题的 BUG 记录。这条记录最后回复更新于几天前,说受其它问题影响,这个 BUG 虽然已经修复,但是并没有推到主版本。实际上,Chromium 团队发现改为标准实现后,一些广泛使用的扩展和一些大站会受影响,所以决定先放一放。

看来即便是技术激进的 Google,也不得不背负一些沉重的历史包袱。既然是这样,难道我的 Chrome 已经穿越到了未来?我百思不得其解。

也不知道过了多久,我突然灵光乍现,想到某次我为了测试一个功能,开启了 chrome://flags 中的「Experimental Web Platform features(实验性网络平台功能)」选项,莫非是这个原因。果然,也不知道从哪个版本开始,Chromium 偷偷修复了这个 BUG —— 只是默认没有启用 —— 除非用户主动打开这个实验性开关。

聊到这里,顺便再说说 document.scrollingElement 这个属性。可能是浏览器厂商们也觉得现在的页面滚动元素太乱,一会儿 BODY 一会儿 HTML,跟页面模式有关,还跟 Webkit 的遗留 BUG 有关,于是搞出来这么个东西。根据 MDN 的介绍:

Document 的 scrollingElement 是一个只读属性,始终指向页面滚动元素。via

这样倒也方便,只是目前它的支持度还很差,需要版本比较高的浏览器:

  • Chrome 44+(PC、Mobile);
  • Safari 9+(PC、Mobile);
  • Firefox 47+(PC、Mobile);

Chrome 在向标准靠拢之前就支持了这个属性,也是一件好事。至少,在只需要支持 Webkit 的场合,这样获取页面滚动元素就没问题了:

var rootElement = document.scrollingElement || docuemnt.body;

最后,以简单小结来结束本文:1)如果发现自己的浏览器有一些跟别人不一样的特性,如果版本相同,那么很可能是受到某些配置项的影响;2)随着时间的推移,Blink(Chrome)和 Webkit(Safari)的差距会越来越大,平时可以多关注下浏览器厂商的升级公告和新的 WEB 标准。

扩展阅读:Dev.Opera Blog : Fixing the scrollTop bug

本文链接:参与评论 »

--EOF--

提醒:本文最后更新于 235 天前,文中所描述的信息可能已发生改变,请谨慎使用。

专题「浏览器」的其他文章 »

Comments