A simple script (based on one by Google) for loading CSS files asynchronously and conditionally based on body tag classes

July 14, 2014 ยท View on GitHub

    <!-- Inlined critical styles -->
    <style>.blue{color:blue;}</style>

    <!-- CSS loader -->
    <script>
    /* ==========================================================================
       Load CSS asynchronously and conditionally after initial painting
       ========================================================================== */

    /**
     * Modified function based on: https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery
     */

    /* Settings */

    // Pass in a string containing your body tag classes here
    // Your CMS will usually have a template function you can use for this purpose
    var bodyClasses = 'class-name-one misc-class awesome-class';

    // Define the class names and CSS files to match up with them
    var pagetypeCssData = [
       {
           test: '', // Leaving this blank will load the files below on every page
           files: ['file-one.min.css', 'file-two.min.css']
       }, {
           test: 'class-name-one',
           files: ['file-three.min.css', 'file-four.min.css']
       }, {
           test: 'class-name-two',
           files: ['file-five.min.css', 'file-six.min.css']
       }
    ];
    // You can reverse the array so the files are processed in reverse order if you wish
    // pagetypeCssData.reverse();

    /* Function to test if (body tag classes) string contains some text */

    function stringHasText(string, text) {
        if(string.indexOf(text) >= 0) {
            return true;
        } else {
            return false;
        }
    }

    var cb = function() {

        /* Function to set media type to all */

        function setMedia(element) {
            setTimeout(function() {
                element.media = 'all';
            });
        }

        /* Loop through pagetypeCssData[] and process the results */

        for (var prop in pagetypeCssData) {
            if (stringHasText(bodyClasses, pagetypeCssData[prop].test)) {
                for (var i = 0, l = pagetypeCssData[prop].files.length; i < l; i++) {
                    var link = document.createElement('link');
                    link.rel = 'stylesheet';
                    link.href = '/path/to/css/directory/' + pagetypeCssData[prop].files[i];
                    // Set media type to something non-matching so it doesn't block the render
                    // Reference: https://github.com/filamentgroup/loadCSS/blob/master/loadCSS.js
                    link.media = 'only x';
                    var firstScriptTag = document.getElementsByTagName('script')[0];
                    // Insert CSS file before first script tag
                    firstScriptTag.parentNode.insertBefore(link, firstScriptTag);
                    // Set the media type back to all
                    setMedia(link);
                }
            }
        }
    };

    var raf = requestAnimationFrame || mozRequestAnimationFrame || webkitRequestAnimationFrame || msRequestAnimationFrame;

    if (raf) {
        raf(cb);
    } else {
        window.addEventListener('load', cb);
    }
    </script>

</head>

<body class="class-name-one misc-class awesome-class">
    <div class="blue">Hello, world!</div>
</body>