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());
}