Skip to content
bbc-frameworks edited this page Oct 6, 2010 · 4 revisions

A Proposal For Supporting CSS Dependencies Via RequireJS

Requirements

A. In order to allow JavaScript modules to define and track CSS rules defined in external files, the developer needs a way to add those CSS files to a module's dependency list, and to cause the loader to wait until that CSS is in effect before the module code is executed. A use case would be a widget that uses the rendered width and height of a particular element as part of the module's internal calculations. If that width and height were controlled by an external stylesheet then the widget would break if it performed those calculations before the related CSS was in effect.

B. In order to allow CSS dependencies to download as efficiently and speedily as possible, the developer needs to have a way to specify the CSS dependency upfront, before the module code is evaluated.

C. In order for CSS dependencies to be loaded from servers at different domains, and to function in all the browsers on the BBC list of supported browsers, the technique used to resolve CSS dependencies must not be limited to same-domain, and must not rely on the onload event of the LINK element.

Rationale

RequireJS does not currently support loading CSS from different domains with a callback. However, we intend to make the RequireJS library available in the global scope of BBC web pages, and RequireJS supports the addition of new features via a plugin, so we should write a plugin for RequireJS that will add this feature.

Because we cannot use AJAX (due to cross domain limitations) and cannot rely on techniques to detect when a stylesheet is loaded into the DOM in browsers like FireFox, we should use a technique that polls for a known style rule being applied to a given element on the page. (see http://otaqui.com/blog/890/cssp-loading-css-with-javascript-and-getting-an-onload-callback/ )

API

Following the model established by other RequireJS plugins, the API for a CSSP plugin would utilise a dependency name like so:

cssp!some/file.css

Because we need to specify what element in the DOM to watch for CSS changes, we should require that information to be appended to the URL, like so:

cssp!some/file.css?myElement

It would be nice if the plugin were flexible enough to watch for any changes to any CSS properties, but to implement the feature as simply as possible we should assume a default CSS property of "z-index" and a default value of "12345". That is, the loaded CSS, in the example, should set the "z-index" of an element with id "myElement" to "12345" as a way of signaling that the loaded stylesheet is now in effect, like so:

/* lots of other CSS rules here */
#myElement{ position: absolute; z-index: 12345; }

Optionally this rule could be automatically added during a build phase, or even at runtime on the server.

A more complete usage example would look like this:

require.def(
    'test',
    ['cssp!test.css?test_101'], // NOTE: this url is relative to config base href
    function() {
        return {
            // module stuff here
        };
    }
);

Implementation

See: http://gist.github.com/613150

Clone this wiki locally