DevTeam-Admin
3/26/2020 - 11:05 PM

Critical CSS boilerplate

Critical CSS

This is scaffolding for implementing critical css into an existing project. Here's what's going on:

  1. The gulpfile contains a new task gulp critical-css that takes an array of urls, and an array of screen resolutions. The screen resolutions are based off the CSS breakpoints used in the project, and the URLs are mapped to page templates (front-page.php, index.php, single-post.php, my-custom-template.php, etc). The gulp task utilizes a headless browser to grab all of the css necessary to render the page "Above the fold".
  2. This css is outputted to PHP files inside the /critical-css/css/ folder.
  3. The file /critical-css/critical.php contains a conditional that loads the critical css for a certain template when that template is requested.
  4. The /critical-css/critical.php is included in the head
  5. the functions.php file contains a new function to preload the main css file, and once it's been loaded, delete the inline critical style

Important notes

  1. If there are css changes on a template that uses critical css, the critical css gulp task will need to be re-run, otherwise the critical css will be out of date and may cause visual issues

Directory Structure

  • dist/wp-content/themes/unicorn-power/critical-css/css/***generated content outputs here***
  • dist/wp-content/themes/unicorn-power/critical-css/critical.php
  • dist/wp-content/themes/unicorn-power/header.php
  • gulpfile.js
// Requires list
...
const critical      = require('critical'); 
// in your terminal run `npm install --save-dev critical`
...

// Inline critical CSS per template file --------------

// Media queries based on CSS breakpoints, adjust to your project
const criticalMediaQueries = [
    {
        width: 599,
        height: 800
    },
    {
        width: 899,
        height: 1024
    },
    {
        width: 1199,
        height: 1080
    },
    {
        width: 1201,
        height: 1080
    }
];

// Definte templates that will have Critical CSS generated
// When adding new entries here, adjust the file at 'template-parts/critical-css/critical.php'
const criticalLayouts = [
    {
        'templateSlug': 'homepage', // generates filename inside 'template-parts/critical-css/
        'src': 'https://rainbowsandunicorns.local' // page to get the critical css from
    },
    {
        'templateSlug': 'blog-index',
        'src': 'https://rainbowsandunicorns.local/blog'
    },
    {
        'templateSlug': 'blog-single', // need an actual URL, so choose a blog post
        'src': 'https://rainbowsandunicorns.local/blog/ten-things-you-didnt-know-about-cheese-whiz/'
    }
];

// Runs the headless browser to generate critical css
// Outputs to the appropriate php
gulp.task('critical-css', function (done) {
    return criticalLayouts.forEach(function (layout) {
        critical.generate({
            src: layout.src,
            css: 'dist/wp-content/themes/unicorn-power/assets/css/main.min.css', // path to your theme css
            dest: 'dist/wp-content/themes/unicorn-power/critical-css/css/' + layout.templateSlug + '.php', // change your theme
            dimensions: criticalMediaQueries,
            minify: true,
            inline: false,
            extract: false,
            ignore: ['@font-face', 'background-image']
        });
    });
});
<style id="critical-css">
    <?php // Add critical CSS for page templates
    if( is_front_page() ) {
        get_template_part('critical-css/css/homepage');
    }
    if( is_home() ) {
        get_template_part('critical-css/css/blog-index');
    }
    if( is_singular('post') ) {
        get_template_part('critical-css/css/blog-single');
    }
    ?>
</style>
<head>
  ...
  <?php get_template_part('critical-css/critical'); ?>
  ...
</head>
function rs_critical_css() {
  global $wp_styles;
    foreach( $wp_styles->queue as $styleHandle ) {
      // this handle needs to match the name of the handle as defined in your stylesheet enqueue function
      if( $styleHandle === 'YOURCSSHANDLE' ) {
        $style = $wp_styles->registered[$styleHandle];
        $source = $style->src . ($style->ver ? "?ver={$style->ver}" : "");
        echo "<link rel='preload' href='{$source}' as='style' onload='this.onload=null;var criticalCSS = document.getElementById(\"critical-css\");if(criticalCSS){this.rel=\"stylesheet\"; document.getElementById(\"critical-css\").innerHTML=\" \"; document.getElementById(\"theme_css-css\").disabled=true};' />";
        echo '<noscript><link rel="stylesheet" href=' . $source .'></noscript>';
      } 
    } 
  }
  add_action('wp_head', 'rs_critical_css');