Prioritize Critical CSS

Configuration

The 'Prioritize Critical CSS' filter is enabled by specifying:

Apache:
ModPagespeedEnableFilters prioritize_critical_css
Nginx:
pagespeed EnableFilters prioritize_critical_css;

in the configuration file.

Objective

This rewriter improves page render times by identifying CSS rules needed to render the page, inlining those critical rules and deferring the load of the full CSS resources.

Description

prioritize_critical_css parses the CSS and replaces it with inlined CSS that contains only the rules used on the page. This avoids any blocking CSS requests needed for the initial render. It also collects all CSS tags and appends them to the HTML in the same order they were found. This will make all style rules available after page load.

Deferring style rules that are not used by the document delays downloading unnecessary bytes and allows the browser to start rendering sooner per this best practice.

Example

For example, if the HTML document looks like this:

<html>
  <head>
    <link rel="stylesheet" href="small.css">
  </head>
  <body>
    <div class="blue">
      Hello, world!
    </div>
  </body>
</html>

And the resource small.css is like this:

  .yellow {background-color: yellow;}
  .blue {color: blue;}
  .big { font-size: 8em; }
  .bold { font-weight: bold; }

Then PageSpeed will rewrite it into:

<html>
  <head>
    <style>
      .blue{color:blue;}
    </style>
    </head>
  <body>
    <div class="blue">
      Hello, world!
    </div>
  </body>
</html>
<noscript><link rel="stylesheet" href="small.css"></noscript>

The original small.css is loaded after onload of the page. The application order of CSS rules is maintained by injecting all the <style> and <link> elements into the document through JavaScript.

The effect of this rewriter can be observed on modpagespeed.com before and after rewriting. You will need to reload the page a few times to see the effect, since this rewriter computes the critical rules for the page based on previous page renders.

prioritize_critical_css injects JavaScript that uses a beacon to report back to the server the CSS that is used by the page. It takes at least two visits to instrument the page, collect the appropriate beacon data, and extract the required CSS before a fully optimized page is presented; until then all CSS is optimized as normal: minified, combined, etc.

prioritize_critical_css automatically enables the rewrite_css, inline_import_to_link, and flatten_css_imports filters since it needs these to be applied to determine the critical CSS, and it automatically disables the inline_css filter as it does this itself. It does this even if these other filters are expressly disabled (or enabled in the case of inline_css) but not if they are expressly forbidden (in which case this filter will do the instrumentation work but ultimately fail to completely optimize the page, wasting processing time).

Requirements

prioritize_critical_css computes critical CSS only if the corresponding CSS file is "public" cacheable.

Risks

prioritize_critical_css filter is moderate risk. It should be safe for most pages, but it could potentially cause reflow of the page. If different content (with substantially different styles) is served for the same URL based on cookies, IP, user agent, etc., then this filter could potentially show unstyled content before it loads the page completely, or in certain cases it could break rendering completely.

prioritize_critical_css filter adds inlined CSS to the HTML, increasing its size. The overhead of the extra inlined CSS can outweigh the benefit if the CSS resources are already in the browser's cache. However it will still benefit from faster processing of the CSS in the browser.

Limitations

This rewriter cannot compute critical CSS for CSS files under IE conditional comments and is disabled if it detects an IE user agent.