//

STYLUS FOR CSS

When your site grows, the CSS can grow along with it, and the maintenance is no longer trivial. You could break your CSS in to different files and use @import to structure it into one file. But this doesn’t resolve all your architecting and maintenance problems.

That is where  Stylus, a CSS pre-processor which is similar to SASS and LESS comes in to play. You can further simplify your code with Jade, but first let's find out how you can set up this Stylus for CSS.

Setup

In Node.js install Express and have Stylus set up as a middleware layer.We need a custom compile function to use some features I will explain later, which looks like this:

function compile(str, path) {
  return stylus(str);
}

Which is then passed to the middleware setup like this:

stylus.middleware({
  src: __dirname + '/public',
  compile : compile
}));

Compress and organize your CSS

For modular CSS files,  @import can be used to encourage the use of smaller, more modular CSS files. However, minimising HTTP requests is the fastest way to gain page load speed and so CSS is often lumped in a huge 1000 loc+ files. You can keep your code modular and legible without the HTTP overhead with Stylus,which  @import directives are parsed on the server. By setting compress : true in the Stylus middleware, compress the CSS output or calling return stylus(str).set('compress', true) in the custom compile function.

Replace Sprite with Stylus

Stylus has the ability to inline images referenced in the CSS as data URIs.

function compile(str, path) {
  return stylus(str)
            .define('url', stylus.url({
              paths : [__dirname + '/public'],
              limit : 10000
            }));
}

limit is the file size threshold (bytes); if the file is bigger than that, then the url is referenced as usual. Although URI encoding images incurs a slight size overhead, the resulting CSS file can be gzipped. This technique means you can reference as many images as you want in your stylesheet without worrying about creating extra HTTP requests.

Vendor Prefixes

Nib is a library for Stylus, which provides cross-browser mixins.  Are you writing CSS like this?

body {
  background: -webkit-gradient(linear, left top, left bottom,
                    color-stop(0, #fff), color-stop(1, #000));
  background: -webkit-linear-gradient(top, #fff 0%, #000 100%);
  background: -moz-linear-gradient(top, #fff 0%, #000 100%);
  background: linear-gradient(top, #fff 0%, #000 100%);
}

What happens if you want to change #000 to #ccc? Pretty painstaking. With nib, you can write this:

body
  background linear-gradient(top, white, black)

Nib jumps in and vendor-prefixes everything for you, so you don't have to worry about it. I literally only use it for that purpose, but it does lots of other useful things if you want it to. To use nib with your custom compile function do this:

// Make sure you install it
// with `npm install nib`

var nib = require('nib');

function compile(str, path) {
  return stylus(str)
            .use(nib());
}

Lose the punctuation

One of my favourite features of Stylus is the syntax. You have the option to go completely punctuation-free: no semi-colons, no colons and no curly-braces, just whitespace and indentation. You could still write regular CSS or you can use the short hand:

*
  margin 0
  padding 0

* {
  margin: 0;
  padding: 0;
}

In the punctuation-free example, only the useful tokens (excl. whitespace) exist, of which there are five. In the punctuated example, there are six extraneous punctuation tokens. It's up to you to choose.

Conclusion

Here is my complete custom compile function:

function compile(str, path) {
  return stylus(str)
    .define('url', stylus.url({
      paths : [__dirname + "/public"],
      limit : 10000
    }))
    .set('filename', path)
    .set('compress', true)
    .use(nib());
}