Using cookies to serve critical CSS for first time visits

Code7 min readView on GitHub

I wrote about critical path CSS earlier in the year, but didn’t cover using cookies to cover the caching part. So, this post will assume that you’ve previously set up your CSS in a similar manner. If not, I advise you read my post about it.

After this post, you’ll be able to setup a cookie, to check if a visitor has the CSS cached and no longer requires the critical path CSS.

Why it’s necessary

Critical path CSS is important for the first page load. There on it’s not really necessary as everything should be cached. It also removes any doubts for the flash of unstyled content.

Our current setup probably looks like

I’ve excluded much of the code for brevity. Just highlighting the <style>, <script> and <noscript> tags used.

<head>
  <style>
    /* Critical CSS */
  </style>
  <script>
    function loadCSS(a, b, c)  {}
    loadCSS('fonts.css')
    loadCSS('full.css')
  </script>
  <noscript>
  </noscript>
</head>

Setting up the cookies

The easiest approach to setting up your cookies is to use the Filament Group cookie utility. It’s a tiny script you can include in your <head> with your loadCSS script.

Setting a cookie using the utility takes 3 parameters. First the name, a string value, and the amount of days until the cookie expires.

cookie('full-css', true, 7);

The first parameter ‘full-css’

This can be anything. I’d advise something memorable, if you want to delete a specific cookie later on.

The second parameter ‘true’

An optional string, can really be anything too. We don’t need to do anything with this, so I have set it to true.

The third parameter ‘7’

Number of days. Again, this can be anything you like as long as it’s a number of days.

We’ve walked through how to set a cookie. Now, we need to check if the ‘full-css’ cookie exists. If it doesn’t, we load inline, our critical path CSS and full CSS in asynchronously. Not forgetting the <noscript> fallback. We will break this code down now to fully understand it.

<?php if ( isset($_COOKIE['full-css']) ) : ?>
  <link href="fonts.css" rel="stylesheet">
  <link href="full.css" rel="stylesheet">
<?php else : ?>
<?php endif; ?>

This part checks if the cookie is set. If we don’t check it’s set we could cause some errors.

Otherwise include critical & full CSS

<?php else : ?>
  <style><?php include 'critical.css'; ?></style>
  <script>
    function cookie(e, i, o) {}
    function loadCSS(a, b, c) {}

    if( ! cookie( 'full-css' ) )  {
      loadCSS( 'fonts.css' );
      loadCSS( 'full.css' );
      cookie( 'full-css', true, 7 );
    }
  </script>
  <noscript>
    <link href="fonts.css" rel="stylesheet">
    <link href="full.css" rel="stylesheet">
  </noscript>
<?php endif; ?>

The chunkier part of the code, we’re making sure we include the critical path CSS and then load the rest asynchronously. A <noscript> fallback is necessary, should any problems occur where Javascript isn’t available.

If you use Typekit, you will have to use their ‘advanced’ script instead.

The final code

<?php if ( isset($_COOKIE['full-css']) ) : ?>
  <link href="fonts.css" rel="stylesheet">
  <link href="full.css" rel="stylesheet">
<?php else : ?>
  <style><?php include 'critical.css'; ?></style>
  <script>
    function cookie(e, i, o) {}
    function loadCSS(a, b, c) {}

    if( ! cookie( 'full-css' ) ) {
      loadCSS( 'fonts.css' );
      loadCSS( 'full.css' );
      cookie( 'full-css', true, 7 );
    }
  </script>
  <noscript>
    <link href="fonts.css" rel="stylesheet">
    <link href="full.css" rel="stylesheet">
  </noscript>
<?php endif; ?>

If you found this article useful, why not support the upkeep of this website?

Get the articles

It’s my aim to help you be a better designer. Join my monthlyish email list and I’ll send new tutorials to help you design & code beautiful websites. You can unsubscribe anytime.

Also, as a subscriber I can provide critique on your designs—send something through after you confirm your subscription.