Loading CSS without blocking render

The principles behind these techniques aren‘t new. Filament group, for example, have published great content on loading CSS and fonts. I‘ve written this article to document my thoughts and ideas for loading non-blocking resources.

The trick to triggering an asynchronous stylesheet download is to use a <link> element and set an invalid value for the media attribute (I‘m using media="none", but any value will do). When a media query evaluates to false, the browser will still download the stylesheet, but it won‘t wait for the content to be available before rendering the page.

<link rel="stylesheet" href="css.css" media="none">

Once the stylesheet has finished downloading the media attribute must be set to a valid value so the style rules will be applied to the document. The onload event is used to switch the media property to all:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!=‘all‘)media=‘all‘">

This method of loading CSS will deliver useable content to visitors much quicker than the standard approach. Critical CSS can still be served with the usual blocking approach (or you can inline it for ultimate performance) and non-critical styles can be progressively downloaded and applied later in the parsing / rendering process.

This technique uses JavaScript, but you can cater for non-JavaScript browsers by wrapping the equivalent blocking <link> elements in a <noscript> element:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!=‘all‘)media=‘all‘">
<noscript><link rel="stylesheet" href="css.css"></noscript>

There is a side-effect to this technique. Once a non-blocking stylesheet has finished downloading the document will be repainted to reflect any new rules it defines. Injecting new styles into the page can trigger content reflows, but this is only really an issue for thefirst page load with an unprimed cache. As with all things related to performance, you‘ll need to make a judgement call on when the need to control a reflow outweighs the potential speed gain.

Using non-blocking CSS to load fonts

Fonts are an issue for first-paint performance, they are a blocking resource and can render text invisible while they download . Using the non-blocking link example above, it‘s possible to download a stylesheet containing font data in the background, unblocking the page render:

<link rel="stylesheet" href="main.css">
<link rel="stylesheet" href="font.css" media="none" onload="if(media!=‘all‘)media=‘all‘">

font.css contains a base64 encoded WOFF version of the Merriweather font.

@font-face {
  font-family: Merriweather;
  font-style: normal;
  font-weight: 400;
  src: local(‘Merriweather‘), url(‘data:application/x-font-woff;charset=utf-8;base64,...‘)
}

main.css contains all the rules required to style the site. Here‘s the font declaration:

body {
  font-family: Merriweather, "Lucida Grande", ...;
}

While the font is downloading, the first matching fallback font (Lucida Grande, in this case) is used to render the page content. Once the font stylesheet is applied,Merriweather will be used. I try to ensure the fallback shares similar layout characteristics to the preferred font, so that the inevitable reflow is as subtle as possible.

I‘m testing blocking vs non-blocking using my Google Analytics Debugger site in Chrome over a simulated 3G connection. Local testing produces the following network graphs; notice the DOMContentLoaded event fires around 450ms earlier and assets begin downloading sooner when non-blocking is used:

Simulated 3G network graph. Top shows blocking fonts. Bottom shows non-blocking fonts.

Deploying this to a test server and running webpagetest with 3G connection shaping produces the following timeline:

3G timeline. Top shows blocking fonts. Bottom shows non-blocking fonts.

Both methods take 2.8 seconds to completely render the page, but the non-blocking method causes painting to being a second earlier than the normal blocking approach. Running the same test with the main stylesheet inlined shows a 0.7 second gain when non-blocking CSS is used to serve the font:

3G timeline with main CSS inlined. Top shows blocking fonts. Bottom shows non-blocking fonts.

This technique does work well for fonts but I recommend keeping an eye on the new CSS Font Loading Module, which gives far greater control over font loading.

Summary

Loading fonts is one example of applying this non-blocking technique, but it could also be used for other purposes, such as separating JavaScript enhanced styles from core CSS.

I‘ve started to experiment with the idea of breaking up CSS into scaffolding (core layout) and presentation (everything else), allowing vital page layout to block the page render and have the visual styles arrive later.

Thanks to Mathias Bynens for taking the time to share a shortened version of the <link>onload handler.

时间: 2024-10-10 06:32:17

Loading CSS without blocking render的相关文章

Render blocking javascripts

What is render blocking? Render means loading, so if a javascript is render-blocking, it means that the javascript is keeping the page from loading. Google recommends 1 to remove or defer javascripts that interfere with loading the above the fold con

CSS Loading 特效

全页面遮罩效果loading css: .loading_shade { position: fixed; left: 0; top: 0; width: 100%; height: 100%; display: -webkit-box; -webkit-box-pack: center; -webkit-box-align: center; background: rgba(255,255,255,.7); z-index: 99 } .loading_box { padding: 30px;

加载框(loading)

一般在用户提交数据或者新加载页面时,请求服务器的过程,页面没有响应,但是用户并不知道,此时在发生什么.这时,就需要loading框给用户提示,增加用户体验. 1.引入loading.css. html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{line-height:1.6;font-family:-apple-system-font,Helvetica Neue,sans-serif}*{margin:0;padd

ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第一章:创建基本的MVC Web站点

在这一章中,我们将学习如何使用基架快速搭建和运行一个简单的Microsoft ASP.NET MVC Web站点.在我们马上投入学习和编码之前,我们首先了解一些有关ASP.NET MVC和Entity Framework的背景信息,然后再详细学习如何搭建开发环境. 1.1 MVC和ASP.NET MVC 这本书涵盖Microsoft版本的MVC,即ASP.NET MVC.在写本书的时候,ASP.NET MVC的生产版本为MVC5,因此,本书的示例代码都使用ASP.NET MVC 5编写.在本书中

JS-easyui 扩展easyui.datagrid,添加数据loading遮罩效果代码

(function (){ $.extend($.fn.datagrid.methods, { //显示遮罩 loading: function(jq){ return jq.each(function(){ $(this).datagrid("getPager").pagination("loading"); var opts = $(this).datagrid("options"); var wrap = $.data(this,"

Normalize.css 初识

一. 用来干嘛的 一个现代的.准备好了支持 HTML5 技术,并且要替代 CSS Reset 处理样式的理念. Normalize.css 使浏览器渲染所有元素更加一致,并且符合现代标准.它只是针对那些需要正常化的样式进行处理. A modern, HTML5-ready alternative to CSS resets Normalize.css makes browsers render all elements more consistently and in line with mod

前端 CSS 规范大全

一.文件规范 1.文件均归档至约定的目录中(具体要求以豆瓣的CSS规范为例进行讲解): 所有的CSS分为两大类:通用类和业务类.通用的CSS文件,放在如下目录中: 基本样式库 /css/core 通用UI元素样式库 /css/lib JS组件相关样式库 /css/ui 业务类的CSS是指和具体产品相关的文件,放在如下目录中: 读书 /css/book/ 电影 /css/movie/ 音乐 /css/music/ 社区 /css/sns/ 小站 /css/site/ 同城 /css/locatio

Cocos Creator—定制H5游戏首页loading界面

Cocos Creator从1.0版本发布到现在也有一年多了,按理说一些常见的问题网上都有解决方案,例如"如何自定义首页加载进度条界面"这种普遍需求,应该所有人都会遇到的,因此也有完善的解决方案才对.我在网上搜了一些文章,虽然也有讨论的帖子,但是方案都不尽人意.因此只能再次自己动手丰衣足食了,在此我总结一下我的思路和策略,分享给大家,希望后来的人少走弯路,另外这里的方案只针对H5游戏发布,其他平台可以借鉴思路自己实现. 首页加载的loading界面,官网的文档并没有提及,我是通过构建发

前端CSS规范大全(转)

一.文件规范 1.文件均归档至约定的目录中. 具体要求通过豆瓣的CSS规范进行讲解: 所有的CSS分为两大类:通用类和业务类.通用的CSS文件,放在如下目录中: 基本样式库 /css/core 通用UI元素样式库 /css/lib JS组件相关样式库 /css/ui 业务类的CSS是指和具体产品相关的文件,放在如下目录中: 读书 /css/book/ 电影 /css/movie/ 音乐 /css/music/ 社区 /css/sns/ 小站 /css/site/ 同城 /css/location