-
Notifications
You must be signed in to change notification settings - Fork 0
Critical Path CSS (Above the fold)
$ npm install --save critical
- grunt-critical
- Gulp users should use Critical directly
- For Webpack use html-critical-webpack-plugin
- Optimize a basic page with Gulp with a tutorial
- Optimize an Angular boilerplate with Gulp
- Optimize a Weather app with Gulp
Include:
var critical = require('critical');
Full blown example with available options:
critical.generate({
// Inline the generated critical-path CSS
// - true generates HTML
// - false generates CSS
inline: true,
// Your base directory
base: 'dist/',
// HTML source
html: '<html>...</html>',
// HTML source file
src: 'index.html',
// Your CSS Files (optional)
css: ['dist/styles/main.css'],
// Viewport width
width: 1300,
// Viewport height
height: 900,
// Target for final HTML output.
// use some CSS file when the inline option is not set
dest: 'index-critical.html',
// Minify critical-path CSS when inlining
minify: true,
// Extract inlined styles from referenced stylesheets
extract: true,
// Complete Timeout for Operation
timeout: 30000,
// Prefix for asset directory
pathPrefix: '/MySubfolderDocrot',
// ignore CSS rules
ignore: ['font-face',/some-regexp/],
// overwrite default options
ignoreOptions: {}
});
Basic usage:
critical.generate({
inline: true,
base: 'test/',
src: 'index.html',
dest: 'index-critical.html',
width: 1300,
height: 900
});
Basic usage:
critical.generate({
base: 'test/',
src: 'index.html',
dest: 'styles/main.css',
width: 1300,
height: 900
});
Generate and minify critical-path CSS:
critical.generate({
base: 'test/',
src: 'index.html',
dest: 'styles/styles.min.css',
minify: true,
width: 1300,
height: 900
});
Generate, minify and inline critical-path CSS:
critical.generate({
inline: true,
base: 'test/',
src: 'index.html',
dest: 'index-critical.html',
minify: true,
width: 1300,
height: 900
});
Generate and return output via callback:
critical.generate({
base: 'test/',
src: 'index.html',
width: 1300,
height: 900
}, function (err, output) {
// You now have critical-path CSS
// Works with and without dest specified
...
});
Generate and return output via promise:
critical.generate({
base: 'test/',
src: 'index.html',
width: 1300,
height: 900
}).then(function (output) {
// You now have critical-path CSS
// Works with and without dest specified
...
}).error(function (err) {
...
});
When your site is adaptive and you want to deliver critical CSS for multiple screen resolutions this is a useful option. note: (your final output will be minified as to eliminate duplicate rule inclusion)
critical.generate({
base: 'test/',
src: 'index.html',
dest: 'styles/main.css',
dimensions: [{
height: 200,
width: 500
}, {
height: 900,
width: 1200
}]
});
This is a useful option when you e.g. want to defer loading of webfonts or background images.
critical.generate({
base: 'test/',
src: 'index.html',
dest: 'styles/main.css',
ignore: ['@font-face',/url\(/]
});
Name | Type | Default | Description |
---|---|---|---|
inline |
boolean |object
|
false |
Inline critical-path CSS using filamentgroup's loadCSS. Pass an object to configure inline-critical
|
base | string |
path.dirname(src) or process.cwd()
|
Base directory in which the source and destination are to be written |
html | string |
HTML source to be operated against. This option takes precedence over the src option. |
|
folder |
string |
HTML source folder. Required to compute relative asset paths in conjunction with the html option |
|
css | array |
[] |
An array of paths to css files, or an array of Vinyl file objects. |
src | string |
Location of the HTML source to be operated against | |
dest | string |
Location of where to save the output of an operation (will be relative to base if no absolute path is set) | |
destFolder | string |
'' |
Subfolder relative to base directory. Only relevant without src (if raw html is provided) or if the destination is outside base |
styleTarget | string |
Target file to store the generated critical-path styles | |
width | integer |
900 |
Width of the target viewport |
height | integer |
1300 |
Height of the target viewport |
dimensions | array |
[] |
An array of objects containing height and width. Takes precedence over width and height if set |
minify | boolean |
false |
Enable minification of generated critical-path CSS |
extract | boolean |
false |
Remove the inlined styles from any stylesheets referenced in the HTML. It generates new references based on extracted content so it's safe to use for multiple HTML files referencing the same stylesheet. Use with caution. Removing the critical CSS per page results in a unique async loaded CSS file for every page. Meaning you can't rely on cache across multiple pages |
inlineImages | boolean |
false |
Inline images |
assetPaths | array |
[] |
List of directories/urls where the inliner should start looking for assets |
maxImageFileSize | integer |
10240 |
Sets a max file size (in bytes) for base64 inlined images |
timeout | integer |
30000 |
Sets a maximum timeout for the operation |
pathPrefix | string |
/ |
Path to prepend CSS assets with. You must make this path absolute if you are going to be using critical in multiple target files in disparate directory depths. (eg. targeting both /index.html and /admin/index.html would require this path to start with / or it wouldn't work.) |
include | array |
[] |
Force include CSS rules. See penthouse#usage . |
ignore | array |
[] |
Ignore CSS rules. See filter-css for usage examples. |
ignoreOptions | object |
{} |
Ignore options. See filter-css#options . |
userAgent | string |
'' |
User agent to use when fetching a remote src |
penthouse | object |
{} |
Configuration options for penthouse . |
user | string |
undefined |
RFC2617 basic authorization: user |
pass | string |
undefined |
RFC2617 basic authorization: pass |
$ npm install -g critical
critical works well with standard input.
$ cat test/fixture/index.html | critical --base test/fixture --inline > index.critical.html
You can also pass in the critical CSS file as an option.
$ critical test/fixture/index.html --base test/fixture > critical.css
var gulp = require('gulp');
var log = require('fancy-log');
var critical = require('critical').stream;
// Generate & Inline Critical-path CSS
gulp.task('critical', function () {
return gulp.src('dist/*.html')
.pipe(critical({base: 'dist/', inline: true, css: ['dist/styles/components.css','dist/styles/main.css']}))
.on('error', function(err) { log.error(err.message); })
.pipe(gulp.dest('dist'));
});
CSS is required to construct the render tree for your pages and JavaScript will often block on CSS during initial construction of the page. You should ensure that any non-essential CSS is marked as non-critical (e.g. print and other media queries), and that the amount of critical CSS and the time to deliver it is as small as possible.
For best performance, you may want to consider inlining the critical CSS directly into the HTML document. This eliminates additional roundtrips in the critical path and if done correctly can be used to deliver a “one roundtrip” critical path length where only the HTML is a blocking resource.
Why, yes!. Take a look at this Gulp project which demonstrates using Critical to generate and inline critical-path CSS. It also includes a mini-tutorial that walks through how to use it in a simple webapp.
The main differences between Critical and Penthouse, a module we use, are:
- Critical will automatically extract stylesheets from your HTML from which to generate critical-path CSS from, whilst other modules generally require you to specify this upfront.
- Critical provides methods for inlining critical-path CSS (a common logical next-step once your CSS is generated)
- Since we tackle both generation and inlining, we're able to abstract away some of the ugly boilerplate otherwise involved in tackling these problems separately.
That said, if your site or app has a large number of styles or styles which are being dynamically injected into the DOM (sometimes common in Angular apps) I recommend using Penthouse directly. It will require you to supply styles upfront, but this may provide a higher level of accuracy if you find Critical isn't serving your needs.
FilamentGroup maintain a criticalCSS node module, which similar to Penthouse will find and output the critical-path CSS for your pages.
Critical has been used on a number of production sites that have found it stable for everyday use. That said, we welcome you to try it out on your project and report bugs if you find them.
Of course. We appreciate all of our contributors and welcome contributions to improve the project further. If you're uncertain whether an addition should be made, feel free to open up an issue and we can discuss it.
This module is brought to you and maintained by the following people:
Apache-2.0 © Addy Osmani, Ben Zörb
Generate and inline critical-path CSS example using Critical.
Live demo of before and after critical-path CSS generation and inlining.
PageSpeed Insights results of before and after
Before:
After:
WebPageTest results
Before:
After:
Use Critical for generating and inlining your critical-path CSS and loadCSS to async load in your site-wide styles.
CSS is required to construct the render tree for your pages and JavaScript will often block on CSS during initial construction of the page. You should ensure that any non-essential CSS is marked as non-critical (e.g. print and other media queries), and that the amount of critical CSS and the time to deliver it is as small as possible.
For best performance, you may want to consider inlining the critical CSS directly into the HTML document. This eliminates additional roundtrips in the critical path and if done correctly can be used to deliver a “one roundtrip” critical path length where only the HTML is a blocking resource.
$ cd critical-path-css-demo
$ npm install && bower install
Note: There are two build commands available. This allows you to compare the difference between the output of a normal build and the output with critical-path CSS.
The default (minify, concat) build for the project can be run with:
$ gulp
The complete (critical-path) build can be run with:
$ gulp critical
This performs the normal build, then generates and inlines critical-path CSS for the page. It automatically async loads in the site-wide styles using loadCSS as part of the workflow offered by the module.
Follow the next few lines to install and scaffold a project using Yeoman and Gulp:
$ mkdir myapp && cd myapp
$ npm install -g yo generator-gulp-webapp
$ yo gulp-webapp
# Select Bootstrap and say no to Modernizr & Sass
You should now have a valid set of source files, including a Gulpfile.js
.
The first thing we're going to do is install the Critical module which can generate and inline your critical-path CSS for you.
This can be installed as follows:
$ cd myapp
$ npm install critical --save-dev
Great. Next, add a reference to Critical at the top of your Gulpfile.js
:
var critical = require('critical');
We can now use it in our build process. Let's write a new task called critical
.
Our workflow for critical-path CSS is to first run a normal build
, which will generate the optimized CSS (dist/styles/main.css
) and resources needed for our app. We pass the build
command as the second argument below:
gulp.task('critical', ['build'], function () {
});
Next, we'll add in our configuration for the critical
module:
gulp.task('critical', ['build'], function (cb) {
critical.generate({
inline: true,
base: 'dist/',
src: 'index.html',
dest: 'dist/index-critical.html',
minify: true,
width: 320,
height: 480
});
});
That's it. You can now run gulp critical
to generate a complete build where dist/index-critical.html
will contain your final output files. Above I've passed in a width
and height
which represent the viewports I'm targeting with my above-the-fold CSS. minify
ensures that the inlined CSS gets minified.
Note that this sample project is just that - a sample. It does not demonstrate how well these tools and techniques work on a complex site nor a site making heavy use of dynamic styles. Your mileage may vary and I encourage testing the tools available before making a decision about whether Critical makes sense for you.