Cutting the Monolith
Modular CSS Preprocessing with Rework
Tl;dr: Don’t always use Sass
If you are writing CSS today, you are most likely using a preprocessor, like Sass, Less or Stylus. After getting used to all the comfort of mixins, variables and your new best friend, the Ampersand, it’s hard to imagine how we could ever have done without them.
However, now that Sass seems on the verge of becoming a de-facto-standard, it might be a good time to take a moment and think about what problems preprocessors are really solving for us and if there couldn’t be other ways to do that.
“Certain front-end development techniques and technologies feel like they’re better suited to product work rather than agency work” — Jeremy Keith
This is a very important point Jeremy Keith made in a recent article about polyfills. Sometimes you hand over pieces of code to a client as deliverables; sometimes you keep working on the same product.
In both cases you are faced by the grim reality of web development, which means you are probably going to need some ugly fixes to account for technologies that are just not quite there yet. But if you are working on an ever evolving code base, as would be the case with product work, you should be thinking about an exit strategy.
Sass has no exit strategy
The great thing about Sass is that it’s one single tool which solves a lot of today’s web designers’ problems with a relatively small amount of configuration. That way, people who weren’t familiar with command line tools before could adopt it fairly easily. The problem is, there is really no easy way back for code once written in Sass.
Once you write for Sass, you have to use a specialized syntax which then undergoes all different sorts of transformations in a single black box which then magically outputs a finished CSS file.
If, for example, somewhere down the road you decided to use standards compliant CSS variables instead of their Sass-counterpart, you would probably have to rewrite a lot of code. Maybe you would even find some kind of hacky way to make Sass replace its own variables with proper ones, but that’s not the point. The point is, preprocessors should allow you to only use a subset of their functionality by design.
Modularize all the things!
If you use preprocessors already, you may probably also have heard of build tools, like Grunt, Gulp or Broccoli. Basically these are all command line tools that take care of a lot of repetitive, boring tasks web designers used to do on a daily basis, like moving files around, stitching them together, optimizing images and what not.
One reason why among all build tools especially Gulp has been gaining a lot of traction in the recent months is its stream-based interface. When you run a Gulp task, you tell Gulp to grab a bunch of files and then pipe them through a series of simple, independent plugins. A typical Gulp task might be:
Take CSS files → Concatenate → Write file to temp folder → Optimize → Write optimized file to production folder
All actions are performed by simple, discrete Plugins which can be combined and reordered in any conceivable way.
If only there was a CSS preprocessor that worked in the same way, right?
Enter: Autoprefixer
A great example for CSS preprocessing done right that’s already used by a lot of people today is Autoprefixer. Autoprefixer takes standard or soon-expected-to-be-standard CSS and makes changes to the syntax, like adding prefixes (duh!), to make it work in all specified browsers.
This is how a preprocessor should work.
It does just one thing and if you don’t feel like using it anymore you just drop it from your development stack and it still leaves you with perfectly valid CSS.
“But what about my variables?,” you might ask. Don’t worry, we’ve got you covered.
Rework: Just like Autoprefixer, except it does nothing
That’s right. If a tool that does only one thing is so good, how great must a tool be that does nothing at all? Problem solved everybody, let’s all go home.
Of course that’s not entirely accurate, but there is actually some truth to that. Rework by itself doesn’t do a whole lot for us front end developers, because it’s just a CSS preprocessing framework that needs plugins to actually do something. And this is awesome!
Let’s take a look at some examples from the list of rework plugins:
- rework-vars — CSS spec style variables
- rework-calc — Add calculations support with a calc() function. Trying to calculate expressions and using CSS3 Calc function as fallback for expressions using mixed units.
- rework-plugin-colors — colors() plugin for rework
- rework-parent — SASS-like parent selectors
- rework-move-media — Aggregate media queries and move them to the end of the CSS file
There you have it. You can combine as many of these plugins as you like to build your very own custom preprocessor. If you want to stay as future-proof as possible, there are lots of plugins that try to emulate future features of CSS. If you want to go crazy and use your good old Ampersand, you can do that, too. If you want to stop using any single functionality, you can always run your production code through the one responsible plugin, drop it from your build task afterwards and you’re good to go.
Of course, Rework integrates nicely with Gulp, too.
So now we got it, right? Everything works beautifully, we can just use tomorrow’s CSS today, right? WRONG!
Caveat
The idea behind Rework is loosely based on Myth. Myth also wanted to tackle the problem of getting new features into CSS with a preprocessor that accepted plain CSS as input, but at first they weren’t very good at it.
Long story short, some future CSS features (using expressions with mixed relative and absolute units like calc(50%-50px), truly dynamic parent selectors, real-time editable variables) only work at runtime, so in these cases Rework “fails silently” and leaves the expression as-is.
Of course, if used with caution, this functionality can still be useful for doing things like .column { width: calc(100%/6) }. But you have to be really careful when and how to use it. If you still don’t see why this could be a problem, you should probably read Rodney Rehm’s article about Myth.
Conclusion
I don’t want to say that preprocessors, as we know them, are bad. It’s great that we have them and it’s even better that so many people know how to use them. Sass is probably the most mature, most stable preprocessor we have right now and I am still using it myself for agency-type work and most likely will continue to do so for quite some time.
But in a controlled environment where you know you will make updates to the code base on a regular basis, you might consider giving more flexible tools like Rework a try.
It’s just a simple case of if all you have is a hammer, everything looks like a nail. The general notion of having a lot of small tools that all do only one thing, and one thing right, is a tried-and-proven concept in computing, so it’s definitely worth keeping that in mind when refining your workflow.
Header image: Daniel Steger, CC-BY-SA-2.5, modified by Frederic Marx