Before starting, please check if you already have critical CSS implemented on your pages. For instance, if you use “WP Rocket” plugin, then it’s the following option: “File Optimization” -> “CSS Files” -> “Optimize CSS Delivery”. Also, you might be using “Autoptimize criticalcss.com power-up” together with “Autoptimize”, etc.

What’s critical CSS?

By default, CSS is treated as a render-blocking resource, which means that the browser won’t render any processed content until the CSSOM (CSS Object Model) is constructed. A visitor will have to wait until all the CSS is loaded, and then content will start showing up on the page.

An optimized page will have the above-the-fold (which is everything the visitor sees before scrolling) printed as soon as possible to offer the visitor a better user experience, even if not all the page’s CSS has been loaded. So, critical CSS has to be used. This is the inline CSS (STYLE tag) that is needed for the above-the-fold to render correctly (e.g. for the top menu, the logo). It’s the first CSS that is read & processed by the browser. The rest of the CSS (non-critical) that is loaded within LINK tags is loaded later on. By the time the visitor scrolls further down the page (e.g. even to the bottom), everything is already loaded.

By inlining, the critical CSS needed (via the STYLE tag) to render the above-the-fold correctly & have the rest of the stylesheets asynchronously loaded, you will offer the visitors a better user experience (the first contentful paint will be faster as the above the fold is shown very fast) and boost the page score in tools such as Google PageSpeed Insights, that will report (prior to the optimization) any render-blocking resource like in the print screen below:

For more print screens and extra information about critical CSS, checkout the following article: https://web.dev/extract-critical-css/. You can also find there, some tools that can help you with the generation of the critical CSS, especially if you’re a developer and have lots of websites to optimize.

Can I just defer all CSS without using any critical CSS?

Asset CleanUp Pro already allows you to defer CSS by moving it from HEAD to BODY (the one that is not critical) and load it when the “load” event is triggered (that’s when all images, stylesheets, scripts, subframes, etc. have been downloaded, so this option is needed for certain CSS that is only needed after the page has been fully loaded) as well as asynchronously loading CSS (preventing it from being render-blocking) via the “Preload (async)” option (this way, the browser will NOT STOP rendering subsequent portions of the page while it requests, downloads, and parses the file). This later method should usually process the CSS sooner (e.g. you know it’s needed immediately after the first content paint, but it’s still non-critical CSS).

While you can completely eliminate render-blocking CSS while using either of the methods mentioned above and have Google PageSpeed report you the score you want, there’s a problem: the user experience. If there’s no critical CSS to style the above-the-fold content, then the user will experience a “Flash of Unstyled Content (FOUC)“. For a few seconds (depending on the internet connection and the location of the visitor as well as other factors such as the hosting), the user will experience something like in the image below (note that the mobile score will report an even higher delay, hence the mobile score is lower than the desktop one when you test your website):

Without Critical CSS (FOUC before CSS is applied)

With Critical CSS (no FOUC)

Showing unstyled content to your visitor even for a second or even less is not professional in any situation. So, if you decide to boost your page speed score and implement critical CSS (it’s not a must as your score can still be very high if you load a few render-blocking resources), you can use the “wpacu_critical_css” filter hook within functions.php in your child theme (or parent theme if you’re positive it’s not the kind of theme that will ever be updated within the Dashboard like you update the plugins, such as a custom theme made from scratch). At the time of writing this (18 May 2020), this is the only way to implement critical CSS via Asset CleanUp as it’s not yet made available to manage it completely within the Dashboard.

How to generate the critical CSS?

First, generate the critical CSS for the page or group of pages that you want. Within your child theme’s root directory, you can create a directory called “critical-css” that could hold the critical CSS files for any custom page or group of pages. The critical CSS can be generated using a tool such as the one from CriticalCSS.com (this is the easiest way, starting from £2/month), Pegasaas’ Critical CSS Generator or if you are a developer or just like to learn more and you don’t have a problem spending some extra time, you can set up some npm modules that are run in conjunction with Grunt or Gulp.

How to use the “wpacu_critical_css” hook?

Ideally, it’s easier to add the critical CSS from the Dashboard (in “CSS & JS Manager” » “Manage Critical CSS”, added in the Pro version from v1.1.9.3) and recommended to do so for page groups (e.g. all “product” pages from WooCommerce). There are situations when you need to do it for custom pages (e.g. a page that is very different than the other ones in terms of layout) and that’s when the hook/filter explained below comes into play:

Reminder: This option is available in the Pro version starting from v1.1.7.2 and you have to be comfortable connecting via SFTP (or use any other way to edit your PHP files) in order to use some WordPress code snippets for the usage of “wpacu_critical_css” filter hook.

The following snippets are examples of how the hook can be used in functions.php (of your Child theme) or even a custom plugin.

Example #1: Implement Critical CSS on a specific customly designed page (e.g. landing page)

add_filter('wpacu_critical_css', static function($args) {
    global $post;

    // Assuming the post ID is 10; If it\'s not, do not continue!
    // It could be a special landing page for which you have a Google AdWords campaign
    if ( ! (isset($post->ID) && $post->ID == 10) ) {
        return $args;
    }

    $landingPageCriticalCssFile = __DIR__.'/critical-css/custom-page-id-10.min.css'; // Server path (not the URL)

    $args['content'] = file_get_contents($landingPageCriticalCssFile);
    $args['minify']  = false; // if possible, have it already minified to save resources

    return $args;
}, 11);

Example #2: Implement Critical CSS on your homepage
Inside “critical-css”, create the file homepage.min.css with the critical CSS content that you generated.

add_filter('wpacu_critical_css', static function($args) {
    $frontPageCriticalCssFile = __DIR__.'/critical-css/homepage.min.css'; // Server path (not the URL)

    if (is_front_page() && is_file($frontPageCriticalCssFile)) {
        $args['content'] = file_get_contents($frontPageCriticalCssFile);
        $args['minify']  = false; // if possible, have it already minified to save resources
    }

    return $args;
}, 11);

Example #3: Implement Critical CSS for posts, pages & WooCommerce product pages
The following example is showing a way to add conditions for various page types. Usually, one critical CSS is enough for a type of page (e.g. product ones). It’s very rare that you might need to add exceptions (e.g. a page of WooCommerce “product” type that is so customized that it needs its own critical CSS version, instead of the one that is applied for the whole group):

add_filter('wpacu_critical_css', static function($args) {
	// Posts (only the standard posts, not custom post types)
	$criticalCssLocalFile = __DIR__.'/critical-css/posts.min.css'; // Server path (not the URL)
	if (is_single() && 'post' === get_post_type() && is_file($criticalCssLocalFile)) {
		$args['content'] = file_get_contents($criticalCssLocalFile);
		return $args;
	}

	// Pages
	$criticalCssLocalFile = __DIR__.'/critical-css/pages.min.css'; // Server path (not the URL)
	if (is_page() && is_file($criticalCssLocalFile)) {
		$args['content'] = file_get_contents($criticalCssLocalFile);
		return $args;
	}

	// WooCommerce product pages
	$criticalCssLocalFile = __DIR__.'/critical-css/products.min.css'; // Server path (not the URL)
	if (function_exists('is_product') && is_product() && is_file($criticalCssLocalFile)) {
		$args['content'] = file_get_contents($criticalCssLocalFile);
		return $args;
	}

	// WooCommerce product category pages
	$criticalCssLocalFile = __DIR__.'/critical-css/product_cat.min.css'; // Server path (not the URL)
	if (function_exists('is_product_category') && is_product_category() && is_file($criticalCssLocalFile)) {
		$args['content'] = file_get_contents($criticalCssLocalFile);
		return $args;
	}

	return $args;
}, 11);
Note that PHP’s is_file() is only working if you put the local path to the file such as /usr/public_html/wp-content/themes/your-child-theme/critical-css/file.css and not the URL to the file: https://www.yourwebsitedomain.com/wp-content/themes/your-child-theme/critical-css/file.css.

What will Asset CleanUp Pro do once there’s critical CSS set to load?

If there’s a critical CSS for the page that is visited by the guest, the plugin will:

  1. Alter the CSS content by minifying it (if you kept the option enabled, although it’s recommended to already have it minified to avoid extra resources to be used) and doing the following changes if they were enabled in plugin’s “Settings”: change @font-face to implement “font-display” (if set in “Local Fonts”), remove Google Fonts (if chosen so in “Google Fonts” – “Remove All”).
  2. Place the CSS content at the top of the <HEAD> section of the page within a STYLE tag (inline code) that has the ID “wpacu-critical-css“.
  3. Then, it will take each of the render-blocking LINK tags & preload them asynchronously, making them non-render blocking and allowing the inlined critical CSS to load first, resulting in a lower “First Contentful Paint” time, which is the desired outcome.
  4. In case JavaScript is disabled (rare cases) in the visitor’s browser, the stylesheets will load as a fallback within <NOSCRIPT> tags placed inside the <BODY> section (bottom) of the page so there won’t be any broken layouts because of missing CSS.

Example: A good example is this documentation website. If you run a test in Google PageSpeed Insights (with Asset CleanUp Pro loaded) you will notice there are no render-blocking CSS resources and the first contentful paint is around 0.9s. If you run the same test without triggering Asset CleanUp Pro at all (by appending /?wpacu_no_load to the URL), you will see a lower score (especially for mobile view) and a first contenful paint of around 0.6s. Note that this website is quite a light one and it might not be as noticeable, but for websites that have a bigger page with more elements, it would make even a bigger difference.

Don’t forget to unload the useless CSS which is not render-blocking anymore!

After the implementation and clearing any caching you might have enabled, you should not have any warnings at all in Google PageSpeed Insights for render-blocking stylesheets. Don’t forget about removing unused CSS even though it became non-critical as it will help with:

  • Reducing unnecessary bytes consumed by network activity, thus saving resources
  • Making sure the browser’s construction of the render tree is not slown down by unused CSS; The render tree is like the DOM tree, except that it also includes the styles for each node. To construct the render tree, a browser must walk the entire DOM tree, and check which CSS rules apply to each node. The more unused CSS there is, the more time that a browser might potentially need to spend calculating the styles for each node.
  • Having a higher page speed score (due to fewer HTTP requests) in GTmetrix & Google PageSpeed Insights which is important for SEO purposes
  • Smaller and easier to go through access log files due to fewer files loaded from the server as well as cleaner HTML source (e.g. good for developers when going through the DOM)

PS: The link to CriticalCSS.com is an affiliate one and I might get a commission if you sign up for their service. I’m recommending it because I used it myself on several websites and I found it to be a reliable solution, compared to other services out there. Please always test your page after you implement any critical CSS to make sure everything is loading smoothly.

Was this post helpful?