KakapoWPKakapoWP
Log inTry for free
Help Center/Performance/Set up Critical CSS

Set up Critical CSS

Applies to: Kakapo Performance·5 min read

What the module does — and what it does not do

For each page template, Kakapo fetches a real sample page of your site over HTTP (only in the admin area or via cron, never while a visitor's page is being built), reads the local stylesheets linked there directly from the hard disk and checks every single rule against the document with DOMXPath. Two results come out of this: the critical CSS that is placed inline in the head, and the list of rules that did not match a single element on this template.

Nothing is rendered in the process. There is no browser, no viewport and no scroll position. “Visible above the fold” is an approximation following a disclosed rule: all elements below body are numbered through, the first 30 percent (default, adjustable between 5 and 90) count as above the fold, plus everything inside the landmarks you entered. Always included are html, body, :root and @font-face as well as @keyframes that a critical rule names via animation. Rules that only take effect through states (:hover, :focus, :active) stay out, and @media print as well. Where the procedure reaches its limit, it rounds up: the rule counts as matched. A few kilobytes too many cost less than a missing rule and flickering.

Checking the requirements before you analyze

Two things have to be right. First, the PHP extension dom/libxml — the module does not check it via class_exists(), it builds a miniature document and really queries it. The reason: some hosts set disable_classes=DOMDocument, and then class_exists() still reports “yes” while the new fails. If the extension is missing, “Analyze” and “Refresh daily” are locked and the reason is stated next to them.

Second, the loopback: the site has to reach itself over HTTP. For that there is the “Check loopback” button in the Requirements area; it remembers the HTTP code, response size and duration. If it fails, every analysis run fails — typical causes are a firewall in front of the site, basic auth protection on the staging environment or a host name that does not resolve internally.

What the analysis cannot read is not deferred either: stylesheets from external hosts, from a CDN or from Google Fonts remain render-blocking, unchanged. That is the slow but safe way.

Working through template by template

There are seven templates: Home page, Blog page, Single post, Static page, Archive, Search results and 404 error page. Each one is analyzed individually and released individually. If your home page shows the post list, “Blog page” is not applicable — the switch stays locked because it would have no effect. If there is no published post or no page, the sample page is missing and the template stays locked as well.

The recommended way: first “Analyze all” or analyze individually. Then, for one template, you open “Preview” and “without” in two tabs — that is the same real page once with and once without the treatment, visible only to logged-in administrators and only with a valid one-time key in the address. The main switch does not have to be on for that. You will spot flickering during page build most reliably in a tab of its own with a throttled connection, not in the embedded frame.

Only once the comparison looks clean do you release the template and switch the main switch on. It starts in test mode: there, only logged-in administrators get to see the treatment, for everyone else the page stays unchanged. You only set it to “live” once you have gone through several templates.

The four brakes and the exception lists

“Load analyzed stylesheets deferred” is the actual time saving. Off means: the critical CSS is added inline on top, otherwise everything stays as it was — risk-free, but without any gain. On means: the evaluated stylesheets load via media="print" plus an onload reset, with a noscript duplicate for visitors without JavaScript. Only what was really read is deferred, and only if the handle and file address still match what was analyzed.

“Pause when source files change” remembers the modification time and size of every evaluated file as well as the active theme. If something changes, nothing is treated at all instead of being treated with possibly wrong critical CSS — the source code then contains a note with the reason.

Three text fields are the emergency exit. Exclusion URLs: one line per path, “*” as a wildcard, these pages are never treated (typically /checkout*, /mein-konto*). Never defer stylesheets: one WordPress handle per line, admin-bar and dashicons by default. Landmarks: one selector per line, everything inside them counts as above the fold — the defaults are header, [role="banner"], .site-header, #masthead, nav, .main-navigation, .site-branding, .hero and h1. Lines that cannot be parsed are rejected instead of being saved silently.

A change to the “above the fold” share or to the landmarks only takes effect after a new analysis run. Everything else discards the page cache immediately, because it holds finished HTML with the old state.

When something goes wrong

“Time budget used up”: the run reached 25 seconds or the PHP time limit. The report is saved, the critical CSS deliberately is not — incomplete critical CSS would flicker. The message names the file where it stopped. Analyze again or take a very large stylesheet out via the exception list.

“Responded with HTTP …”: the sample page did not return the expected code (200, and 404 for the error page). Nothing is saved. Check whether the page is reachable in the browser and whether some protection sits in front of it.

A template is marked “outdated”: an evaluated CSS file has changed or the theme was switched. Analyze again. If it says “different share”, the template was created with a different percentage than the one set now — analyze again as well.

So that this does not stay manual work, there is “Check and refresh daily”. The cron run only analyzes templates that are already released and outdated; it never switches anything on and does not create an analysis for a template that has not been released. Its last result appears as a note in the Seat belt area.

If a page still remains restless, a look at the source code helps: it contains a comment with the template that was treated and the state (preview, test mode, live) or the reason why it was deliberately not treated.

Was this article helpful?