Addressing a few CSS pain points using the Grails Resource plugin
Motivation: CSS is great, but it comes with a few annoying things.
The familiar waterfall of redundancy
/* The joys of vendor prefixes */
.rounded {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ie-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}Same result with the plugin
#define radius 5px
.rounded {
border-radius: ${radius};
}Pain point number one - No variables
First of all, if you ask a CSS purist he'll probably tell you that introducing variables and logic in CSS is evil and that you my friend should burn in you-know-where just for coming up with the question.
You can, at least to a certain degree work around the lack of variables by creating rule sets per feature (like font color and so on) and apply that to a list of selectors. This kinda works, but starts to break apart in larger applications, especially if you want to break it into modules. It's also difficult if you want to apply the same colors to different elements without repeating the color several places in your stylesheet.
Call me a CSS barbarian, but I'd like to have CSS variables! I agree that CSS is better off without more complex logic.
Pain point number two - All those browser vendor prefixes
Browser vendor prefixes are great as they let you start using CSS3 draft features, but repeating the same line over and over again with a different prefix is laborious, error prone and reduces readability considerably.
Motivation
A couple of days ago I forgot to update a value in one of those vendor prefixed lines (all those hex color values looks pretty much all the same to me after a couple of hours of coding). After a lot of proper Norwegian swearing I figured that it was about time to look into one of those new hip and cool languages compiling down to CSS. LESS, SASS and Stylus seems to be the most popular choices these days. Amongst those I found Stylus most interesting.
The problem is that they're all written in Ruby or JavaScript. Not that there is anything wrong with that, it's possible to run both Ruby and JavaScript on the JVM, but introducing a huge new dependency just to rewrite CSS is just not an option. I want something addressing the two problems mentioned above while integrating nicely with Grails.
Writing a resource mapper
The Grails ecosystem consists of quite a few plugins by now, many of them are just thin wrappers around existing projects providing a smoother integration with Grails. The Resources plugin on the other hand is one of the really innovative Grails plugins. It introduces a DSL for configuring of static resources and a concept of mappers. Mappers can hook into the pre-processing of static resources and do pretty much anything from gzipping, rewriting, obscuring to minifying.
I figured that hacking together a quick resource mapper (see link at the bottom of the page for source code) addressing my two main annoyances shouldn't be too much work - and for once it turned out that it wasn't! Writing a resource mapper was an incredible pleasant experience! Thanks to a convenient API and hot reloading support it was just a matter of writing a couple of CSS files and start hacking on the mapper while hitting F5 in the browser until it provided the desired result.
Example - Variables
I had a look at the suggestion for CSS variables and figured that it would be too much work to implement it without writing a parser, so I went for a very simple implementation.
Variables can be defined and used in a way that should be at least somewhat familiar to Groovy and Grails developers. Note it's implemented using a pretty naive regex so you won't be able to add logic inside the curly braces.
#define textcolor #333
body {
color: ${textcolor};
}
Potential gotcha: All variables are stored in the mapper and re-used across resource reloads so variables defined in one stylesheet might leak into an unrelated file. This should not be a problem as defining a variable will replace any pre-existing variables with the same name.
Example - Rule processors
I've implemented something I call rule processors to address the vendor prefix problem. They can be defined in your existing *Resources.groovy files. Grails developers should find them familiar to taglibs.
modules = {
// Define modules as you usually do
}
cssProcessors = {
"border-radius" { args ->
out << "-webkit-border-radius: $args;\n"
out << "-moz-border-radius: $args;\n"
out << "-ie-border-radius: $args;\n"
out << "-o-border-radius: $args;\n"
out << "border-radius: $args;\n"
}
}
This processor will be invoked for every occurrence of border-radius in your stylesheets. Output from the processor will replace the matched line in the stylesheet so you'll have to print the original rule as well if you want this behavior.
Example - Implement your own CSS rules
Processors can also be used to implement your own CSS rules like in the example below.
cssProcessors = {
"-x-linear-background" { args ->
def (start, stop) = args.split(",")
out << "background-color: $start;\n" // fallback color
out << "background: -moz-linear-gradient(-90deg, $start, $stop);"
out << "background: -webkit-gradient(linear, left top, left bottom, from($start), to($stop));\n"
}
}
Comments or ideas?
I'm currently evaluating the plugin on a staging server running an experimental branch of one of my company's projects. It looks very promising so far, but do note that the plugin is very young and likely to contain bugs and gotchas.
Any comments or suggestions? I don't mind contributing it to the central plugin repository if more people find it useful. If nobody else is interested it'll just keep on living in an internal plugin repository at my company.
The code is as usual hosted on GitHub.


Peter McNeil - 06. May 2011 15:41
Nice, I like the fact you can "macro" out the unpleasant compatibility issues. My GSParse plugin gives you GSP inside any file, which lets you put code and variables inside CSS and JS (or any other file) if that's all you want, whereas Resources does a lot more. Thanks for the write up.