❗ 本文最后更新于 3983 天前,文中所描述的信息可能已发生改变,请谨慎使用。
通常,css 文件都会放在页面 head 引入,这样可以避免页面加载时由于样式缺失而引发的跳动。有时候,我们也有需要异步加载 css 文件的场景,如按需加载某些自带外链 css 的模块。本文描述我在 webkit 下异步加载 css 文件遇到的两个奇怪现象。
另外,本文提到的问题要想绕过去很容易,有各种各样的办法,本文只描述现象本身。
首先来看本文测试用到的 loadCss 函数:
var loadCss = function(i) {
var defererd = when.defer();
var link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
var css = cssList[i];
link.onload = function() {
log(css + ' is ok.');
defererd.resolve();
};
link.href = base + css;
document.getElementsByTagName('head')[0].appendChild(link);
return defererd.promise;
};
这里引入 promise 是为了后面并发加载 css 更方便。另外由于本文只考虑 webkit,而比较新的 webkit 支持了 link 的 onload 事件,所以这里不需要做兼容性处理。这部分代码很简单,不需要多解释。
奇怪现象一
试想,用上面的函数并发加载多个 css,浏览器会在什么时候解析并应用它们呢?是每个 css 下载完单独生效,还是要等到全部 css 都下载完再一起生效呢?我之前一直认为是前者,firefox 确实是前者,但 webkit 的表现却是后者。
var cssList = ['css1.php', 'css2.php', 'css3.php'];
when.all([loadCss(0), loadCss(1), loadCss(2)]).then(function() {
log('all done.');
log('time:' + (new Date - date));
});
以上代码,一共并发加载了三个 css,它们分别被我在服务端 delay 了 1s、3s 和 5s。测试结果表明,webkit 会等最慢的那个下载完才开始应用这三个 css 文件。通过下图可以清楚看到,前两个 css 下载完,UI 并不会得到更新。
这里是测试地址,请用最新的 safari 或 chrome 测试,并留意控制台的日志。
这个现象背后,应该是 webkit 对 css 渲染所做的优化:为了避免造成页面元素抖动(如前后两个 css 都有作用于某个元素的规则),在尚有 css 未加载完时,不进行渲染。个人觉得比较好的做法是设置一个超时,避免某些特别慢的 css 请求造成页面傻等。不知道 webkit 是否有这样的机制,但我尝试把本例中某个 css 的 delay 改到 30s,结论还是一样。总之这个策略有点奇怪。
奇怪现象二
我发现的另外一个奇怪的现象是,webkit 在异步加载 css 时,UI 更新会变得很节制,一定要移动鼠标或者鼠标点击才更新。
这个现象测试地址在这里,用最新的 safari 或者 chrome 都能复现。
本例中,我用前面写的 loadCss 函数加载了一个 delay 30s 的 css,同时启动定时器,每 200ms 更新一次页面某元素的内容,但在 webkit 中,如果鼠标不动,或者鼠标移出了浏览器窗口,页面就静止不变了。
我们知道,现代浏览器都会在浏览器窗口不可见时提高定时器间隔,但上面这个现象明显跟这没关系。不知道这次又触发了 webkit 什么优化策略,总之更奇怪。
PS:我 Google 到一篇类似的文章「webkit css-on-demand issues」,看来这个诡异的问题一直都存在。
更新 @ 2016.04.12:本文描述的现象一在 Chrome 50+ 中已修复;现象二也已修复(具体修复版本没有考证);Safari 中依旧还是老样子。
本文链接:https://mailseason.com/post/webkit-load-css-issues.html,参与评论 »
--EOF--
发表于 2013-12-25 22:18:14,并被添加「CSS、Webkit」标签。查看本文 Markdown 版本 »
专题「浏览器」的其他文章 »
- iOS 10 Safari 视频播放新政策 (Oct 07, 2016)
- Chrome 中 scrollingElement 的变化 (Apr 16, 2016)
- 域名小知识:Public Suffix List (Nov 28, 2015)
- window.opener.location 安全风险讨论 (Oct 09, 2015)
- 使用 SRI 增强 localStorage 代码安全 (Sep 26, 2015)
- Subresource Integrity 介绍 (Sep 23, 2015)
- 移动 Web 与 JavaScript 定时器 (Mar 27, 2014)
- Chrome 和 Web Fonts 二三事 (Mar 24, 2014)
- 小成本实现部分选中的复选框 (Dec 22, 2013)
- Chrome 滚动条冻结现象 (Dec 02, 2013)
Comments
Waline 评论加载中...