Skip to main content

filter · CSS filters

Prioritize critical CSS (prioritize_critical_css)

Category:
CSS
CoreFilters:
No
OptimizeForBandwidth:
No
Risk:
Test first

Inlines the CSS rules a page uses and loads each full stylesheet without blocking the first paint. The full stylesheet is preloaded from the place its <link> had in the page and takes effect there as soon as it has arrived, so the order in which your rules apply does not change; a <noscript> copy of the link covers visitors without scripts, and inline <style> blocks are left as they are. By default the inlined rules cover every element in the page as visitors’ browsers last saw it, so content further down the page is styled from the first paint too.

How it works

Uses a JavaScript beacon to collect critical CSS data from real user visits. The beacon endpoint must be accessible for data collection to work. Can cut perceived load time, but test it against your own page layouts first. In v1.15.0+r18 and later, the filter honors a restrictive Content-Security-Policy when HonorCsp is enabled: on pages whose policy disallows inline styles or scripts, it passes the page through unchanged instead of injecting content the policy would block. For the trade-offs behind critical-CSS extraction, see how critical CSS is identified.

If you prefer a smaller inline block and accept that content below the first screen may be partly styled until the full stylesheet arrives, turn on CriticalCssAboveTheFoldOnly (off by default): ModPagespeedCriticalCssAboveTheFoldOnly on on Apache, pagespeed CriticalCssAboveTheFoldOnly on; on nginx, pagespeed CriticalCssAboveTheFoldOnly on on IIS.

What to expect. After you deploy a changed stylesheet, the filter leaves that page’s stylesheets blocking for a few page views, until visitors’ browsers have reported on the new rules. After a page’s markup changes without its stylesheets changing, rules that newly apply can be late until a visitor’s browser reports on the new markup; the module asks for a report again after about a minute by default (twelve times BeaconReinstrumentTimeSec), and the wait is longer when the visitor who is asked does not report. The browser reports which rules the page uses once the page has loaded, so content that a script removes, hides or gives other class names before then can be painted without the rules that applied only to its earlier state, until the full stylesheet arrives. Content a script adds while the page is loading takes its rules from the full stylesheet. The full stylesheet is turned on by a small inline script: if something in front of your server delays inline scripts, the full styles arrive when that script runs. For pages whose markup differs from visitor to visitor under one URL, leave the filter off (DisableFilters prioritize_critical_css for that location).

A stylesheet keeps its ordinary blocking <link> when it uses an @import the server cannot merge into it, when nearly all of it would be inline anyway, or when its <link> carries an event-handler attribute, a title or disabled. A page with more matching selectors than one report can carry keeps its blocking stylesheets until a complete report arrives (see the beacon_overflow_count statistic). The filter needs the beacon and therefore does nothing on Envoy.

When to use it

  • Not in CoreFilters: it runs only when you enable it by name.
  • Risk rating on these docs: Test first.

Risks

The CSS filters page lists no specific risks for this filter. If a page misbehaves with it, DisableFilters prioritize_critical_css turns it off for the scope you set it in.

Configuration

Enable it in the module configuration, at server, virtual-host or location scope:

Apache

ModPagespeedEnableFilters prioritize_critical_css

nginx

pagespeed EnableFilters prioritize_critical_css;

IIS (pagespeed.config)

pagespeed EnableFilters prioritize_critical_css

On the worker

The worker runs its own pipeline, configured by flags. Its equivalent of this filter is the critical css transform. Always-on under pagespeed on; (it is part of the HTML optimization pipeline disabled only by --disable-html).

Scoping, ForbidFilters and the thresholds filters read: Choosing filters .

Live example

Inlines above-the-fold CSS and loads the rest after first paint.

This filter changes how the page is structured or delivered, not its size, so the example shows a source diff rather than a byte or request reduction.

See the before and after, with the source diff →

Frequently asked questions

What does the prioritize_critical_css filter do?
Inlines the CSS rules a page uses and loads each full stylesheet without blocking the first paint. The full stylesheet is preloaded from the place its <link> had in the page and takes effect there as soon as it has arrived, so the order in which your rules apply does not change; a <noscript> copy of the link covers visitors without scripts, and inline <style> blocks are left as they are. By default the inlined rules cover every element in the page as visitors' browsers last saw it, so content further down the page is styled from the first paint too.
Is prioritize_critical_css enabled by default?
No. prioritize_critical_css is not in CoreFilters, the default RewriteLevel; it runs only when you enable it by name with EnableFilters.
How do I enable prioritize_critical_css on Apache and nginx?
Add ModPagespeedEnableFilters prioritize_critical_css on Apache or pagespeed EnableFilters prioritize_critical_css; on nginx. On IIS, add pagespeed EnableFilters prioritize_critical_css to pagespeed.config.

This page is drawn from the prioritize_critical_css entry on CSS filters. Every filter in one table: PageSpeed filters.

Search