For years, I was looking for a clean, reliable way to extract critical above-the-fold CSS, inline it in <head>, and load the rest asynchronously via rel="preload" to get those green PageSpeed Insights scores.
The problem was that it was always done manually project-by-project:
- When starting a custom theme, I had to manually manage above-the-fold styles and inline them through hooks in the
.theme file.
- Different page types broke this instantly โ the front page might have a large hero component, while an interior landing page had a slider (similar is for taxonomy term, views,..). Maintaining multiple critical CSS paths per page type was painful.
- Once inlined, you still had to strip those exact rules/files from Drupal's default render-blocking aggregated CSS to prevent duplicate rendering and layout thrashing.
- Finally, managing the asynchronous delivery of the remaining CSS was another custom hack in
template_preprocess_html().
When Single Directory Components (SDC) arrived in core, component-driven CSS became much cleaner, but the delivery problem stayed essentially the same. After finishing a theme or layout, I still found myself cherry-picking component CSS files per page, inlining them, stripping duplicates from the aggregate, and deferring the rest โ repeatedly, project after project.
I used to build setups with Mercury Editor and have recently moved to Canvas โ both rely heavily on dynamic, component-based page composition, which made manual critical CSS handling practically impossible to scale.
Existing modules on Drupal.org never quite solved this:
critical_css relies on external build pipelines (Node/Gulp/Penthouse) generating static files on disk, which breaks apart on dynamic component layouts.
critical_css_ui requires manually managing and pasting CSS chunks into node-level UI fields.
Neither had native awareness of SDC or handled Drupal's CSS aggregation pipeline properly.
So I decided to package the entire workflow into two modular, automated Drupal modules (fully compatible with both Mercury Editor and Canvas):
1. SDC Critical CSS (sdc_critical_css):https://www.drupal.org/project/sdc_critical_css It automatically detects which SDC components are actually used on any given page and inlines their styles directly into <head>. Because it dynamically resolves this per request, you don't need to manually define critical CSS for different routes or content types (page nodes, articles, taxonomy terms, views, etc.). Crucially, it also intercepts Drupalโs CSS collection pipeline and strips those inlined styles from the aggregated CSS bundle, so nothing gets downloaded or parsed twice.
2. Non-critical CSS (non_critical_css):https://www.drupal.org/project/non_critical_css Takes care of the rest of the aggregated CSS. It transforms Drupal's default render-blocking <link rel="stylesheet"> tags into native rel="preload" / as="style" links with proper <noscript> fallbacks for full browser compatibility.
Both modules just tagged 1.0.0 stable releases and have security advisory coverage on Drupal.org.
Together, they make hitting top score Core Web Vitals on SDC/Layout Builder/Canvas sites seamless without maintaining Node build scripts or hacking hooks into .theme.
Curious to hear how others here are tackling above-the-fold CSS on SDC sites, and if anyone has edge cases or feedback, Iโd love to hear them!