Working with Critical CSS

This is a high-level overview of how the Critical CSS API processes styles.

Jacob Feltner avatar
Written by Jacob Feltner
Updated over a week ago

Overview

This is a high-level overview of how the Critical CSS API processes styles.

  1. We render the page in a 1300x900 browser.

  2. All styles that affect an element in the initial viewport are kept as critical CSS.

  3. All styles that affect an element outside of the initial viewport are kept as non-critical CSS.

  4. Styles that don't affect an element anywhere on the page are stripped from the non-critical CSS.

When a user visits the site, we'll load only the critical CSS by default. The non-critical CSS will be loaded when the user scrolls, or after 2 seconds – whichever happens first.

Concepts

Force Non-critical CSS

In order to serve the smallest stylesheets possible, when processing non-critical CSS, we strip out any styles that don't affect page elements. This creates issues when the critical CSS process doesn't recognize that a selector is present in the page markup. Typically, these would be styles that target selectors that are added by JavaScript after the page loads – the browser that we use to determine styles does not execute JavaScript at runtime, so these styles will not be "picked up."

For example, given this markup and CSS:

<div class="plugin-wrapper"> <div class="plugin-child">Hello world</div> </div> <style> .plugin-wrapper { color: blue; } .something-else { color: red } </style>

The resulting CSS would be:

.plugin-wrapper { color: blue; }

because .something-else is not present from the page HTML when it loads.

In order to circumvent this behavior, you can specify an allowlist option. This can either be a CSS selector or a regular expression that would match a selector. Either of these options would work:

.something-else // CSS selector some // Regex

Because either value "matches" a selector, the styles will be retained in the non-critical CSS.

Force Critical CSS

By default, if a selector is present in the page but not in the initial 1300x900 viewport, it will be included in the non-critical CSS file. This might not be desired behavior – it's possible that you need some styles to be present at page load instead of when the user interacts with a page. This might help prevent layout shift or prevent "flash of unstyled content" behavior for elements close to the viewport.

Consider the following HTML and styles:

<div class="plugin-wrapper"> <div class="plugin-child">Hello world</div> <!-- imagine the next element renders below the viewport --> <div class="something-else">Hello world</div> </div> <style> .plugin-child { color: blue; /* Force .something-else to be below viewport. */ margin-bottom: 100vh; } .something-else { color: red; } </style>

The resulting critical CSS would be:

.plugin-child { color: blue }

and the resulting uncritical CSS would be:

.something-else { color: red; }

To circumvent this behavior, you can specify a force critical CSS option. This too can either be a CSS selector or a regular expression that would match a selector.

Getting Selectors

Different plugins will have different approaches for structuring class names. To figure out what selectors to use, right-click a page element and select "Inspect." This will open up your browser's element inspector, which allows you to see what class names the plugin uses.

Many plugins will have a "prefix" in their class names. Here, we can see that WP Recipe Maker's class names all contain wprm-. With this in mind, we know that we can use wprm as the selector.

User-uploaded Image

Having a standard class name prefix is by no means guaranteed for a plugin, but it's considered a good practice in the WordPress community, so it's where we would recommend starting.

Specifying options

Selectors can be specified programmatically in your functions.php file. Replace my-selector with each selector, you want to design as "non-critical" or "keep critical."

/**the idea is anything set to color blue can't be purged from critical css */ function theme_allowlist_styles(){ return [ '/animate$/', ~~~~'/pop-up$/' ]; } add_filter( 'mv_trellis_css_allowlist', 'theme_allowlist_styles' );s; });

Selectors can also be set in Appearance > Trellis > Advanced using the "Force Non-Critical CSS" and "Force Critical CSS" field.

Note: If you add selectors to "Force Critical CSS", we recommend checking your posts in a Google Page Speed Insights report afterward as this may cause an "Unused CSS" warning to be flagged on any pages where these selectors are being forced into Critical CSS.

Did this answer your question?