CSS.load [logo]

An asynchronous CSS loading promise library

CSS.load

A brilliant library for asynchronously loading CSS and executing callbacks via a cross-browser compatible promise API.

Inspired by: loadCSS, css-onload.js, and Only.js.

Why CSS.load?

There are basically four reasons why CSS.load was born. They are (in no particular order):

  1. To prevent the delay of page rendering when stylesheets (not critical to initial page rendering) referenced with link[rel=stylesheet] or @import are being downloaded.
  2. To have a straightforward and simple API for: stylesheet insert points, and deep browser support (IE8+) for callbacks.
  3. To be the Only.js of asynchronous CSS loading.
  4. To assist Only.js for faster page loads.

CSS.load ensures you're able to load non-critical stylesheets asynchronously, so they don't block page rendering.

Basic Usage

In it's basic form, simply call the load function and pass it a stylesheet URL:

$CSS().load("path/to/stylesheet.css");

The code above will insert a new CSS stylesheet link after the first meta CSS.load finds in the head, and will return a chainable promise-like callback API with a reference to the link. Multiple calls to CSS.load will reference CSS files in reverse the order they are called, but may finish loading in a different order than they were called depending on network conditions.

Automatic Usage

Newer browsers are beginning to support a standard markup pattern for loading CSS (and other file types) asynchronously: <link rel="preload"> (W3C Spec).

The markup for referencing your CSS file looks like this:

<link rel="preload" href="path/to/stylesheet.css" as="style">
<noscript><link rel="stylesheet" href="path/to/stylesheet.css"></noscript>

The current implementation of this markup pattern is to load these asynchronous CSS with low priority. CSS.load will act as a polyfill for browsers that support or don't yet support this new feature by automatically converting them to stylesheets (and download with higher priority).

NOTE: rel=preload does not apply the CSS on its own. CSS.load will try fetching these stylesheets asynchronously (the browser cache will be used for supported browsers) and apply the CSS as soon as the CSS finishes loading. Since CSS.load requires JavaScript, you may want to include a reference to your CSS file using a noscript element to ensure it only applies in non-JavaScript environments.

NOTE: Be sure that your CSS file will be referenced from the same spot in the source order as the original link element whether the browser supports rel=preload or not. Keep this in mind, as you may want to place the link in a particular location in your head element so that the CSS loads with an expected cascade order.

You can view a demo of this rel=preload pattern below: # Online Tests

Function API

When you're calling CSS.load manually (without the rel=preload pattern.

Methods


[$CSS] $CSS(object optionsObject)

Sets one or more options to be in effect for the current chain being executed. This method is chainable and must be chained. It is (obviously) the first call in the chain (as it internally calls a setOptions() method).

Parameters
optionsObject : an object which contains name/value pairs for the options to set:

Returns
$CSS : the chained object reference so subsequent calls to load() can be made.

Example
$CSS({
    insertAtElement: 'link.theme-base', // the first link tag with class="theme-base"
    insertBefore: true, // insert before 'link.theme-base' element
    basePath: '//cdn.my-cdn.com/assets/css/', // use a different base path
    allowDuplicates: true, // browser may fetch CSS from cache
    cacheBust: true // always request a fresh CSS
});

[$CSS] $CSS().load(varies,...)

This method accepts one or more parameters of varying types. Each parameter value is intended to specify a stylesheet resource URI to load.

Parameters
varies (can be any number/combination of the following):

Returns
$CSS : the chained promise object reference so subsequent calls to done(), fail() and always() can be made.

Example
$CSS().load([
    "path/to/stylesheet-1.css",
    ["path/to/stylesheet-2.css", "path/to/stylesheet-3.css"],
    {
        href: "path/to/stylesheet-4.css",
        class: "print-theme",
        media: "print"
    },
    function(){
        // can perform any funny logic here :)
        return "path/to/stylesheet-5.css";
    }
], "path/to/stylesheet-6.css", "path/to/stylesheet-7.css");

NOTE: The returned chained object does not include load() ie, subsequent calls to load() such as $CSS().load().load() cannot be made. This feature is intentional.


[$CSS] $CSS().load().done(function inlineScript(ss_obj)[=null])

This function is used to run a callback function reference (usually an inline anonymous function) when each stylesheet specified with .load() has been successfully loaded.

Parameters
inlineScript : The callback function to run when stylesheet has been successfully loaded. Sets a reference to the current stylesheet that was successfully loaded as the first parameter.

Returns
$CSS : the chained promise object reference so subsequent calls to done(), fail() and always() can be made.

Example
$CSS().load(["path/to/stylesheet-1.css", "path/to/stylesheet-2.css"])
    .done(function(ss_obj){
        // attribute 'data-href' holds the default uri before any uri rewrite
        window.console.info(ss_obj.getAttribute('data-href') + ' was successfully loaded');
    });

[$CSS] $CSS().load().fail(function inlineScript(ss_obj)[=null])

This function is used to run a callback function reference (usually an inline anonymous function) when each stylesheet specified with .load() has failed to load.

Parameters
inlineScript : The callback function to run when stylesheet has failed to load. Sets a reference to the current stylesheet that failed to load as the first parameter.

Returns
$CSS : the chained promise object reference so subsequent calls to done(), fail() and always() can be made.

Example
$CSS().load(["path/to/stylesheet-1.css", "path/to/stylesheet-2.css"])
    .fail(function(ss_obj){
        // attribute 'data-href' holds the default uri before any uri rewrite
        window.console.info(ss_obj.getAttribute('data-href') + ' failed to load');
    });

[$CSS] $CSS().load().always(function inlineScript(ss_obj)[=null])

This function is used to run a callback function reference (usually an inline anonymous function) when each stylesheet specified with .load() has either successfully loaded or failed to load.

Parameters
inlineScript : The callback function to run when stylesheet has either successfully loaded or failed to load. Sets a reference to the current stylesheet that has either successfully loaded or failed to load as the first parameter.

Returns
$CSS : the chained promise object reference so subsequent calls to done(), fail() and always() can be made.

Example
$CSS().load(["path/to/stylesheet-1.css", "path/to/stylesheet-2.css"])
    .always(function(ss_obj){
        // attribute 'data-href' holds the default uri before any uri rewrite
        window.console.info(ss_obj.getAttribute('data-href') + ' was either successful or unsuccessful');
    });

[$CSS] $CSS().noConflict(none)

noConflict() rolls back the page to the previous version of $CSS (if any) before CSS.load was executed, and returns the current instance of $CSS.

Parameters
none

Returns
$CSS() instance : the current $CSS() instance (from before the rollback)

Example
window.loadCSS = $CSS().noConflict();
loadCSS().load("path/to/stylesheet.css");

Usage Tips

I typically use CSS.load to load CSS files that are non-critical to the initial rendering of a page.

NOTE: The rel=preload pattern is used for faster asynchronous stylesheet loading as it is fetched as soon as CSS.load is executed. See this page's source for a live example of how it's used to improve page loading performance.

Online Tests

Below are in-browser tests:

  1. Loading Stylesheets (a) without promise
  2. Loading Stylesheets (b) with promise
  3. Automatic rel=preload Polyfill
  4. Insert At Position
  5. Adjust Basepath
  6. Loading Multiple Stylesheets (a) with promise
  7. Loading Multiple Stylesheets (b) with promise
  8. Loading Same Multiple Stylesheets (a)
  9. Loading Same Multiple Stylesheets (b)
  10. Loading From CDN (a) without promise
  11. Loading From CDN (b) with promise

Browser Support

CSS.load attempts to load a css file asynchronously in any JavaScript-capable browser. However, some older browsers will block rendering while the stylesheet is loading. This table outlines css loading support and async loading support.

Browser CSS Loads Successfully CSS Loads without Blocking Render
Chrome Mac (latest and many recent versions) Yes Yes
Firefox Desktop (latest and many recent versions) Yes Yes
Opera Mac (latest and many recent versions) Yes Yes
Safari Mac (latest and many recent versions) Yes Yes
Safari iOS (latest and many recent versions) Yes Yes
Chrome Android 5.x Yes Yes
Chrome Android 4.x Yes Yes
Android Browser 2.3 Yes No
Kindle Fire HD Yes Yes
Windows Phone IE 8.1 Yes Yes
IE 11 Yes Yes
IE 10 Yes Yes
IE 9 Yes Yes
IE 8 Yes Yes
IE 7 (no querySelector() support) Yes Yes
IE 6 (no querySelector() support) Yes No