Render-blocking stylesheets are one of the most common LCP and FCP bottlenecks on WordPress sites. The solution — extracting the CSS required to render above-the-fold content (“critical CSS”) and inlining it in <head> while loading the full stylesheet asynchronously — eliminates the render-blocking request entirely. The challenge is automating extraction and keeping the critical CSS up to date as theme styles change.
Problem: WordPress generates a full page of HTML and CSS on every request — the full stylesheet is downloaded before the browser can paint the above-fold content, even though only a fraction of CSS is needed for the initial viewport.
Solution: Automate critical CSS extraction using the critical npm package in your build pipeline — it loads the page in a headless browser and extracts only the CSS rules needed for the initial viewport. Inline the critical CSS via wp_add_inline_style() and load the full stylesheet asynchronously using rel="preload" + onload.
The code below generates critical CSS with critical (a Node.js CLI tool), stores it per post type, inlines it via wp_head, and loads the full stylesheet non-blocking using the media swap trick.
# Install the critical CSS CLI tool
npm install -g critical
# Generate critical CSS for the homepage (viewport 1300×900)
critical https://helloadmin.com/ \
--width 1300 --height 900 \
--inline false \
--css wp-content/themes/my-theme/style.css \
> wp-content/themes/my-theme/critical/home.css
# Generate for single posts
critical "https://helloadmin.com/?p=1" \
--width 1300 --height 900 \
--inline false \
--css wp-content/themes/my-theme/style.css \
> wp-content/themes/my-theme/critical/single.css
' . file_get_contents( $critical_file ) . '' . "\n"; // phpcs:ignore WordPress.WP.AlternativeFunctions
}
}, 1 );
// Remove the normal blocking stylesheet and replace with async load
add_action( 'wp_enqueue_scripts', function () {
// Remove default enqueued stylesheet
wp_dequeue_style( 'my-theme-style' );
}, 100 );
// Add a non-blocking preload link + noscript fallback
add_action( 'wp_head', function () {
$stylesheet = get_stylesheet_uri();
// media="print" + onload swap is the standard async-CSS pattern
printf(
'' . "\n"
. '' . "\n",
esc_url( $stylesheet )
);
}, 5 );
NOTE: Regenerate the critical CSS files whenever the theme stylesheet changes — stale critical CSS causes flash-of-unstyled-content (FOUC) as the page repaints when the full stylesheet loads; automate regeneration in your deployment pipeline with a post-deploy critical CLI step.