Improving ‘time to first load’ and generating critical CSS for Drupal and WordPress sites

This document is a work in progress….

One thing that we want to fix is ‘time to first load’. As you probably know, people are recommending to put as little in the way of initial loading as possible, and zero external requests. This means no blocking JS in head, and as little CSS as possible, placed inline instead of in an external file – the so-called ‘critical.css’

Our situation was very much the opposite. Most of our sites are on Drupal or WordPress, with quite a few plugins, which generate a lot of CSS and JS. For wordpress, we often use a theme called Divi, which is quite powerful, but it generates a LOT of css and js, and a lot of it we don’t need.

We started by working on CSS, and then moving onto JS.

CSS

  • Using a web inspector, like Firebug or Safari’s developer tools, take a look at your <head> element. Copy all of the internal CSS files and inline CSS you see there into a single stylesheet (External css, like webfont importing, leave for the moment). If a css file has an @import statement from another file, you have to replace the @import statement with the contents of that file. For example – our WordPress main theme style.css has an import statement from Divi style.css. You will now have a VERY big single css file – lets call it style1.css
  • There are some tools you can use to make the CSS file a bit more manageable. I would recommend first to use a tool like CSS Compressor with Moderate settings so that the file is still readable.
    Then, as much as you can, you can set about removing unused css and combining ‘duplicate’ and overriding css statements that were formerly in different files. You dont need to aim for absolute precision here; if you are not sure about some css, you can just leave for later. This applies especially if you are not familiar with the theme. There are some command line tools and paid online tools that can help you with removing unused and duplicate CSS.
  • Now that you have a single file, you can use a free critical css generator, which will generate some critical css. You should save this into a seperate file called critical.css
  • Then you remove all of the css out of style1.css that is already inside critical.css. Diffmerge for Mac helped with this: you can export a ‘diff’ which unfortunately contains some extra characters but you can remove with search/replace. This file is now your new style1.css.

Now we want to put the contents of critical.css inline in the header, and place style1.css in the footer just before all the footer js, and remove all of the other CSS.

  • In WordPress, you can disable all theme CSS in your function.php file: See this solution on stack overflow (Note: we may need to modify this for logged-in users). You can then override the header.php file in your theme, and add a php include statement for the critical.css file just above wp_head() to load the contents directly
    <style type="text/css"><?php include get_stylesheet_directory() . '/.critical.css'; ?></style>
    Note that if you have an external CSS like webfont, for now it is good to just place there manually.
    Then you should place the style css file manually in your footer.php file just above wp_footer. It is probably best to rename this to style.css and make it your theme style file, complete with theme info on top.
    <link rel="stylesheet" href="<?php include get_stylesheet_directory() ?>./style.css" type="text/css" media="all">
  • In Drupal 7 you can also disable css in your theme template.php file, and load certain css for admins

/* Unset all the base drupal stylesheets */
function themename_css_alter(&$css) {
global $user;
$admincss = array(
drupal_get_path('module', 'user') . '/user.css',
drupal_get_path('module', 'contextual') . '/contextual.css',
drupal_get_path('module', 'ckeditor') . '/css/ckeditor.css',
drupal_get_path('module', 'admin_menu') . '/admin_menu.css',
drupal_get_path('module', 'admin_menu') . '/admin_menu.uid1.css',
drupal_get_path('module', 'domain_admin') . '/domain_admin.css'
);
$temp = $css;
foreach($temp as $key => $data) {
if(!$user->uid || !in_array($key, $admincss)) {
unset($css[$key]);
}
}
Then you can override html.tpl.php and paste the critical css file above the $styles variable.

<style><?php include drupal_get_path('theme', 'yourtheme') . '/critical.css'; ?></style>

and the style css file at the bottom above the $page_bottom variable

<link rel="stylesheet" href="<?php include drupal_get_path('theme', 'yourtheme') ./style.css" type="text/css" media="all">

Cleaning up icon fonts

Some themes (eg wordpress Divi) has its own icon font or import a common font, which is pretty big! We should use fontello to create our own much smaller font based on the icons you actually use and import this one instead.

Javascript

more to come…

Comments are closed.