在浏览器加载CSS 时防止影响页面渲染的方法

所属分类: 网页制作 / CSS 阅读数: 807
收藏 0 赞 0 分享

 本文展示了一种技术,它能通过异步下载样式表,以阻止它们的下载阻塞页面的渲染,从而尽可能快的让访问者获取到信息内容。

警告! 我发这篇帖子全是好意,但是它并不负责让读它的人意识到下面将会遇到的问题. 社区很快地给了我许多的反馈 (有些反馈我很感激) ,而越来越明显的是这项技术并不如我所希望的那样稳定. 不像我那样的成功地对它进行了测试和利用,许多开发者在 IE 和 Firefox 中都遇到了问题( F F测试版中直接崩溃) 而其他人则报告在 Chrome 和 Safari 中是成功的。我现在的建议是: 不要将其用于产品。我计划处理好这些反馈,并结合任何有关的信息对本文进行更新。


这些技术背后的原理不是新的。例如灯丝(Filament)技术组已经发布了大量有关 加载CSS 和字体的内容. 我写就本文以记录我对加载非阻塞资源的想法和观点。

触发异步样式下载的诀窍是使用一个 <link> 元素,并 为media 属性设置一个不可用的值 (我用的是 media="none", 不过其它的任何值也是可以的)。当一个媒体查询的结果值计算出来是 false 的时候,浏览器仍然会下载样式表,但是不会在渲染页面之前等待样式表的资源可用。
 

CSS Code复制内容到剪贴板
  1. <link rel="stylesheet" href="css.css" media="none">  

样式表一下载好,media 属性就必须被设置一个可用的值,以便样式规则能被应用到 html 文档中onload 事件就可以用来将 media 属性切换到all:
 

CSS Code复制内容到剪贴板
  1. <link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">  


这种加载 CSS 的方法将比标准的方法在向访问者传送有用信息的速度上快很多。至关重要的 CSS 加载时仍然可以用一般的阻塞方式处理 (或者你也可以为了最终的性能对它进行内联处理) ,而不重要的样式则可以慢慢下载,并在解析/渲染过程的后面一点的阶段进行应用.

这一技术使用了 JavaScript,但是你也可以在一个<noscript>元素中封装一个等价的阻塞方式的 <link> 元素来处理不能运行 JavaScript 的浏览器:
 

CSS Code复制内容到剪贴板
  1. <link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">   
  2. <noscript><link rel="stylesheet" href="css.css"></noscript>  

这项技术有一个副作用。当一个非阻塞的样式表完成加载,文档就将进行重绘,以反映它定义的任何新的样式规则。而注入新的样式到页面中会触发内容回流, 但这也只是在这对第一次没有历史缓存的页面加载过程中会是一个问题。由于任何跟性能有关的东西,你都将要在需要控制一次回流耗费超过潜在的速度优势时,进行必要的调整。
 
使用非阻塞 CSS 加载字体

字体第一次绘制的性能是一个问题,它们是阻塞式的资源,也会让应用它们的文本在该字体下载时不可见 。使用上述示例中的非阻塞链接,就可能在幕后下载包含字体数据的样式表,不阻塞压面的渲染:
 

CSS Code复制内容到剪贴板
  1. <link rel="stylesheet" href="main.css">   
  2. <link rel="stylesheet" href="font.css" media="none" onload="if(media!='all')media='all'">  

font.css 包含一个 base64 编码的 WOFF 版本的 Merriweather 字体
 

CSS Code复制内容到剪贴板
  1. @font-face {   
  2.   font-family: Merriweather;   
  3.   font-stylenormal;   
  4.   font-weight: 400;   
  5.   srclocal('Merriweather'), url('data:application/x-font-woff;charset=utf-8;base64,...')   
  6. }  

main.css 包含了需要应用到站点的所有样式规则。下面是字体的声明:
 

CSS Code复制内容到剪贴板
  1. body {   
  2.   font-family: Merriweather, "Lucida Grande", ...;   
  3. }  

当字体正在下载时,第一个匹配到的备用回退字体 (这里就是 Lucida Grande) 被用来渲染页面的内容。 一旦字体样式表被应用了,Merriweather 就会被使用. 我尝试去确保回退的字体将相似的布局特征共享给优先选择的字体,那样不可避免的回流就尽可能微妙了。
 

我在基于一个模拟的 3G 网络连接的 Chrome 中,使用我的 Google Analytics Debugger 站点 拿阻塞和非阻塞方式进行了对比测试。本地的测试产生了如下所示的网络图;注意 DOMContentLoaded 在更早的 450ms 触发了,而资源在运用了非阻塞技术后下载起来更快了:
2015626180714510.png (1092×475)

模拟 3G 网络的图形。顶部显示了阻塞式的字体。底部显示了非阻塞式的字体。

将其部署到一个测试服务器并在 3G 连接环境下运行 webpagetest 构造产生了如下时间线 :
2015626180738512.png (1898×327)

3G 时间线。顶部显示阻塞式的字体,底部展示非阻塞式的字体。


两种方法都花了2.8秒钟来完整的渲染页面,但是非阻塞方法比一般的阻塞方法使得绘制早了1秒钟。在在主样式表进行了内联的情况下运行相同的测试,显示了在将非阻塞 CSS 被应用于处理字体时有0.7秒的时间优势:
2015626180845431.png (1898×327)

主 CSS 内容的 3G 时间线。顶部显示阻塞式字体,底部显示非阻塞式字体。

这一技术对于字体的效果确实很好,但是我也建议对新的 CSS 字体加载模块保持密切关注,它会给与我们超过字体加载的更多的控制能力。

总结

加载字体是应用非阻塞技术的一个例子,而他也可以被用于其它的目的,比如从核心的 CSS 处分离出 JavaScript 增强的样式。

我已经开始去尝试将样式分成框架(核心布局) 和展现 (其它所有的东西)这种想法,它可以让重要的页面布局阻塞页面渲染,而可见的样式数据延迟一会。

更多精彩内容其他人还在看

CSS入门教程:计算CSS盒模型宽和高

 出处:当我们布局一个网页的时候,经常会遇到这样的一种情况,那就是最终网页成型的宽度或是高度会超出我们预先的计算,其实就就是所谓的CSS的盒模型造成的。 #test{margin:10px;padding:10px;width:100px;height:100px;}
收藏 0 赞 0 分享

在IE流览器中正确显示PNG透明图片

  png图片有很好的品质。阴影效果也不会有杂边,很流畅。如果插入网页的话可以给网站内容增色不少!更重要的是在不增加图片容量大小的情况下提高了页面的图片的质量。对于有复杂背景,如:在有颜色过度背景上插入不规则边框的图片带来极大很便利!   但目前IE中对于插入
收藏 0 赞 0 分享

CSS教程:DIV底部放置文字

  css对文字的布局上没有靠容器底部对齐的参数,目前使用的一个不错的方法也比较好.就是用position属性来解决,看下面的代码,用position的相对和绝对定位功能也轻松的实现了,文字靠近div低部对齐,并且靠近的距离还可以精确到像素,自己可以调节,是不是很不错呢?
收藏 0 赞 0 分享

如何用CSS让文字居于div的底部

  这个问题是别人提出的,因为css对文字的布局上没有靠容器底部对齐的参数,(或许有但是我没有发现)不过目前我使用的一个不错的方法也比较好.就是用position属性来解决,看下面的代码,我用position的相对和绝对定位功能也轻松的实现了,文字靠近div低部对齐,并且靠近
收藏 0 赞 0 分享

从A页面连接到B页面后并直接把B页面的隐藏层显示

  这个效果实现的是,在B页面里有两个层,一个显示层,我们暂定名c层,一个是隐藏层,我们暂定名d层,单独进B页面的时候,c层显示,d层隐藏,然而从A页面连接到B页面的时候,则是让d层显示,c层隐藏,我觉得这个效果对网页设计者以后会有很大帮助,现在把代码发出来,
收藏 0 赞 0 分享

CSS样式表定义标签li前面样式

定义LI前面的小点样式 view plaincopy to clipboardprint? 语法: list-style-type : disc | circle | square | decimal | lower-roman | upper-roman | lowe
收藏 0 赞 0 分享

符合标准的div css制作的弹出菜单

本文介绍了五款符合标准的div css制作的弹出菜单,而且不含有js的. NO.1最基本的:二级dropdown弹出菜单 <!DOCTYPE html PUB
收藏 0 赞 0 分享

CSS实现在文章每段后面加入带连接的隐藏文字

代码主要理解3个参数:createElement、createTextNode、appendChild。这3个js参数分别是创建元素、创建字符、追加节点。代码原理:循环页面段落标签<p>,创建连接元素<a>,创建要显示的连接字符,用SetAttribute
收藏 0 赞 0 分享

CSS:浏览器特定选择器介绍

当你想在一个浏览器里改变样式而不像在其他浏览器中改变时,这些选择器很有用。 IE6以下 *html{} IE 7 以下 *:first-child html {} * html {} 只对IE 7 *:first-child html {} 只对IE 7
收藏 0 赞 0 分享

WEB标准学习,认识两种网页声明的含义

即网页标准推出来以后,我们时常会看到两种不同的网页的声明,一个是Dhtml,一个是Xhtml。如下所示: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "ht
收藏 0 赞 0 分享
查看更多