Dojorama Part 7: CSS Loading & Theming

This article is part of the series Dojorama: Building a Dojo Single Page Application

We need a way to organize our CSS into reasonably small chunks and load them dynamically as needed. Probably you'll be using a combination of the following techniques to cover your specific requirements:

Global Styles

There's a good chance that we will want to statically load some CSS which is global to the application as a whole. We are using Twitter Bootstrap for this application, so we'll create styles/global.less and add Bootstrap stuff in there. We might also add custom styles for components such as navigation, header and footer.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="/styles/global.css">
    </head>
</html>

global.css is generated from global.less. LESS extends CSS with variables, mixins, operations and functions. We'll use a little utility named Less.app to transform our own LESS files. Open Less.app and add /styles to let it watch for changes in this directory. Whenever we save a file, Less.app automatically generates the CSS.

Dynamic Per-Page CSS Using <style>

We've already seen this approach in part 1 and 2 of this tutorial where we put the home page styles into a separate file which is then loaded by our page widget and placed inline into a <style> tag within our document. Luckily, the Dojo loader's text plugin and Dojomat transparently handles this stuff for us, all we have to do is define a dependeny to a CSS file and call setCss(...) on the page widget with the contents of this file:

ui/home/css/HomePage.css

body {
    background: yellow;
}

ui/home/HomePage.js

define([
    "dojo/_base/declare",
    "mijit/_WidgetBase",
    "mijit/_TemplatedMixin",
    "dojomat/_AppAware", // setCss()
    "dojo/text!./templates/HomePage.html",
    "dojo/text!./css/HomePage.css" // the css to be placed in <style>
], function (
    declare,
    _WidgetBase,
    _TemplatedMixin,
    _AppAware,
    template,
    css
) {
    return declare([_WidgetBase, _TemplatedMixin, _AppAware], {
        templateString: template,

        postCreate: function () {
            this.inherited(arguments);
            this.setCss(css, 'all'); // creates a <style media="all"> element and inserts the css
        }
    });
});

This is great and everything but as we'll see in the next article, CSS added in this way will be baked into our widget code when creating a production build for our application. Hence, only the stuff specific to any one particular page should be added using this pattern. One big advantage of this technique is, that the CSS is readily available when the DOM elements of your dynamic page are added to the DOM, thus eliminating Flashes of Unstyled Content (FOUC).

Conclusion

With the CSS in place, we are finally ready to bake a fresh and optimized build for production deployment!