Lean css in javascript

by Guido Tapia

in software-engineering,

April 19, 2010

This weekend I was looking at the lesscss.org project and found it very interesting. There is also a .net implementation. The basic features of these projects is to make css less verbose, they do this by offering features like mixins, variables and nested rules. Now all of this is very straight forward lexical analysis to produce raw css so I thought to myself why does this need a server side component, what if I want to have a pure html site. I don’t want php, ruby, .net, etc just to compile some css. I also don’t want an additional deployment process to compile my css. So… Why not javascript.

I thought there must be some limitations but a very quick test shows that it is entirely possible. So here we go:

We want to prevent the bowser from doing 2 requests to css so change all your:

<link rel='stylesheet' href='style.css'/>

With:

<link rel='lss' href='style.css'/> <!-- I have called it lss for less but it can be anything -->

This will prevent the borwser from requesting this file, which is good as we will be manually requesting them. So now lets add a script file to load and parse our lss files:

<script src="jsless.js" type="text/javascript"></script>  

Content of jsless.js (Note I’m using jQuery)

[code:js]
$('link').each(function() {
var lss = $(this);
var lssurl = lss.attr('href');
// Should we make this block? Probably, but lets leave for now
$.ajax({url: lssurl, dataType:"text", success: function(css) { getcsscallback(lss, css); }});
});
function getcsscallback(lss, cssText) {
var vars = getVariables(cssText);
for (var i in vars) {
i = trim(i);
var val = trim(vars[i]);
cssText = cssText.replace(/@[A-z^:]+:.*/g, ''); // remove var line
cssText = cssText.replace(new RegExp(i, 'g'), val); // replace replace variables
}
cssText = '<style>' + cssText + '</style>'; // TODO: Add media, etc, etc from the attributes of lss into this tag
$('head').append(cssText);
}
function getVariables(cssText) {
return getMatches(/(@[A-z^:]+):([^;]+);/g, cssText);
}
/// Following code is just supporting regex and string manipulation code
function getMatches(regex, text) {
var matches = {};
var match = null;
while (match = regex.exec(text)) {
matches[match[1]] = match[2];
}
return matches;
}
function trim(str, chars) {
return ltrim(rtrim(str, chars), chars);
}
function ltrim(str, chars) {
chars = chars || "\\s";
return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}
function rtrim(str, chars) {
chars = chars || "\\s";
return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
}
[/code]

Thats it, I have a test project set up that you can use to see this in action. You can also just click here to see the html. The css (lss) used is here and the js is here.

I personally think this project has some potential so if you are interested in working with me just email me and we can set up an OS project and start from there.

Note, I have tested the above in chrome, firefox and IE8 and it appears to work.

Anyways hopefully this inspires someone to do this properly.

Thanks

Guido Tapia

Software Development Manager

PicNet Pty Ltd