Precompiling CSS with Extensions - A Crazy Idea?
I've had this idea for a while, and I think it's a good one. I hope someone else will run with it, because I would love to have a tool that does what I'll describe. If the consensus is that it's a dumb idea, then so be it. Web developers who either don't use CSS (!) or are abstracted away from CSS by a WYSIWIG tool or development framework might not be too excited by this idea, but I suspect it will resonate with people who hand-code their CSS. My idea is for a "precompiler" (if that's the best label) for Cascading Style Sheets (CSS).
What I mean by this is a tool that allows me to leverage procedural and object-oriented concepts like named constants, variables, inheritance, and references to increase the coding efficiency and maintainance associated with web sites that have somewhat complex CSS code. Just to be clear, my proposal has nothing to do with changing CSS itself. I just want to get rid of some of the tedium and inefficiency in the coding and maintanence of CSS, especially for sites large and complex enough to be interesting.
When I use the term "pre-compiler" I'm thinking of the browser that renders HTML content with CSS styles as the primary "compiler." The browser parses the CSS code associated with the HTML (for simplicity's sake, let's assume the CSS is in a separate file than the HTML) and decides how to display the web page. My idea is for a standardized set of extensions to the normal CSS syntax that provide shortcuts for the CSS coder, and a "pre-compiler" that parses the "extended" CSS code to output "normal" CSS code.
Let me try an example:
One of the top features I'd like to see in this CSS extension is named constants. For example, I want to do something like this:
~const PRIMARY_BACKGROUND_COLOR = "#FFFFFF"~
body {
background-color: ~PRIMARY_BACKGROUND_COLOR~;
}
div.inset {
background-color: ~PRIMARY_BACKGROUND_COLOR~;
}
div.inset_reverse {
color: ~PRIMARY_BACKGROUND_COLOR~;
}
I think that people who code a lot of CSS, especially complex CSS that is split across multiple files, will immediately see the benefit of being able to define a value that repeats often in the CSS and only put it in one place. This is an obvious use of the DRY principle (Don't Repeat Yourself) that programmers in procedural and object-oriented languages use all the time. We could apply the same idea to all sorts of CSS values: font families, weights, styles, etc.; height and width dimensions; image filenames; border styles--the sky's the limit.
That tilde (~) that I put in front of the const defintion and is just a marker for the precompiler to distinguish this as a CSS extension that needs to be handled. No doubt someone smarter about language design and lexical parsing than me can come up with a better convention. I'm just trying to get the idea across.
(Please keep in mind that this is only a contrived example. I'm well aware that CSS has inheritance mechanisms built in such that DIVs inside of the BODY will inherit the background color from the BODY. But it's often not that simple, and I've run into plenty of flakey browser-specific CSS inheritance issues over the years.)
So the idea here is *not* that we would send this "extended" CSS out to the browser. Rather, we would use our "pre-compiler" to turn this into valid CSS. The benefit to me as the CSS coder is that I can save time and reduce mistakes by defining constant values in one place and then refer to them wherever I need to.
Another idea is what I call "references." For example, I want to be able to say, in effect, "Make this attribute have the same value as the same attribute on this other style." For example:
li {
line-height: 1.4em;
}
blockquote {
line-height: ~SAME_AS(li)~;
}The idea is that we can refer to another style within the same scope, not unlike the idea of the named constant. Again, this is just a contrived example. I'm well aware that we could have just put li and blockquote together in the same style defintion, separated by a comma, but consider that there might be other attributes we don't want to share for these two tags. And also, my syntactic convention with the tildes and the function-like SAME_AS() may not be lexically ideal.
I think there are probably other similar ideas that we could come up with, but I'll stop here. If we wanted to get really fancy, we could introduce the ability to define macros or scripts that could be "called" from within a style definition, such that the pre-compiler would execute that code to determine what the resulting CSS should look like. For example, some simple math support would be useful:
li {
line-height: 1.4em;
}
blockquote {
line-height: ~SAME_AS(li) - .1em~;
}What I like about this is that it allows me to set the style values of some page elements *relative to* other elements.
As far as implementation of this idea, I suppose one could develop a full-blown CSS IDE around it, but I suspect a plugin for an existing tool like Eclipse or Dreamweaver might be a better idea. Myself, I would love to have it as a feature of my favorite text editor, UltraEdit, but if there was a command line compiler that my editor could call, I think that would work just as well and might make for the most universally accessible solution. It would be cool to have a unique file extension to, like *.CSSE, for "CSS Extensions." That way I could configure UltraEdit with the CSS Extensions syntax highlighting rules.
I would prefer to see this as implemented in an Open Source manner, or even better as some kind of standard that could be implemented in multiple tools, commercially or otherwise. But beggars can't be choosers.
Feedback welcome.
Thanks for reading,
Daniel Read

This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Built it.
Hey, Daniel. Here's how I decided to tackle this problem, using the aforementioned C preprocessor to do the heavy lifting. I hope this'll work for you.
CSS compiler...
I too have had this very thought. At the time, ignorant of the CSS specification, I searched in vain for such an animal in the wild w3. I eventually came across the spec, and my dream was flattened, but still alive. I considered writing a Q&D VB EXE that would pre-process my css and never found the time. Roberts suggestion is much cleaner that I would have come up with, but I don't like the fact that it piggy backs on the c code, thus losing native CSS functionality... I'll check back and see if ayone else solves this ... It would be interesting to see if the W3C could justify it's inclusion in the next CSS Spec, however unlikely that rteally is.... Thanks for your thoughts. D.
Reply to Robert's CPP Solution
Hello,
I wrote the following comment to Robert Hahn's excellent post and solution, to which Robert links in this comment up-thread. However, I think Robert's server was having some trouble at the same time I was posting the comment, so I am pasting the comment below.
Best,
Dan
*****
Robert, this is great! Thanks for taking the time. In addition to being a nice initial solution to the problem, it's an excellent demonstration of the power of generic tools like CPP and launchd. While reading your post, I was thinking of how easy it would have been for the original designer of CPP to make the tool less generic.
The clash between CSS and CPP on the meaning of the # character is an unfortunate side effect, even more so because I use this convention in my CSS liberally--that is, starting a style definition with the # character, as in your example foo:
#foo {
...
}I suppose CPP could have been designed to be even more generic if the definition marker character was configurable. Easy to criticize the play from home after the match has already been played.
Previously, Robert, I described your solution as an "initial solution." In this, I meant no disrespect, because I think it's infinitely cool that you've put this together. I'm going to give it a run myself for a new site I'm about to build, and I suspect others will find it useful also. Not to mention, I suspect others will find inspiration from the creative application of CPP.
You mentioned in your post that you had only skimmed my original post, which is cool, and regardless, I might have not done the best job explaining my overall
"extensions" idea, which includes more than the string-replacement functionality from my first "const" example--a problem which is solved nicely by your CPP-based solution. I think a full implementation of the "extensions" idea would need to have more semantic awareness, if that phrase is appropriate, of the specific structure of the CSS code.
What I mean is, I would also love to have that ability to refer to other styles in a manner where this "precompiler" would understand the other styles defined in the scope of one or more designated CSS files as "objects." This to me implies the need to initially parse all of the designated CSS files to build a graph in memory of unique style "objects," kind of like parsing an XML file to build a DOM.
In addition, the ideal solution I can imagine at this point (and I'm not pretending to be the most qualified person to do so) would have some ability to evaluate simple expressions and functions, such as the example of saying "I want this lineheight attribute value to be .1em less than the lineheight attribute of that other style over there."
Thanks also for the introduction to the term "lazyweb request."
Best,
Dan
P.S.
The timing with the Slashdotted interview you mentioned is coincidental. I've been sitting on this idea for awhile and finally the other night decided to blog on it since it was clear I was not going to have the time to do something with the idea myself. I imagined, however, that I could not have been the first person to think such thoughts. The need for these kinds of "extensions" would be apparent I think to a lot people coding CSS of interesting complexity from scratch. I'll have to go read that interview.
I'm back.
Sorry about my blog not accepting your post; I found out this morning, right before running out with my family for the day that the server I'm on went belly-up. It's a shared server, so the usual presumption at this point is that some over-enthusastic developer tried to do something that consumed too much of the server's resources. Anyhow: the blog's back up and running.
Thank you very much for your kind words. I too saw this as a first cut at the solution, and had this mostly written up before I discovered the problem with #foo and cpp. Before seeing Dennis' and your comments on that problem, I mostly convinced myself that it wasn't that bad. As an aside: I'm not quite following Dennis' issue with the "piggybacking on the C code" - Dennis, if you're reading this, please understand that the C preprocessor has nothing to do with the C language - the people who wrote it designed it to specifically solve their problem with writing lots of C code. The preprocessor can be used with other languages, and other text files (and indeed, this is how I used it).
In any event, I'm going to have a look at using gm4, which won't have this conflict with id selectors. I realized, after posting my article, that for this type of exercise, gm4 might be a better fit -- the problem with gm4 is that it's too powerful, it's really hard for many developers to pick up, and can match things a tad too aggressively if you set it up wrong. For those reasons I instinctively reached for CPP.
After reading carefully through your post and this response, Dan, I have a better understanding of wanting a tool that can understand CSS well enough to refer to information from other rules, but I'm having quite a bit of trouble seeing what it buys CSS developers. The way I see it, what you're asking for, if used in real life, will result in CSS that looks like spaghetti code - you're simply using named GOTO's.
In the case where you want your li and blockquote rules share the same font size definition, I'd probably still would want to just define it in a set of constants (using names like default, caption, header1, header2, header3), and, if I find I'd need to tweak a size, I'll either adjust it on a 'global level' or simply change which constant to use. For arithmetic support, well, maybe using gm4 might actually help here, because it promises arithmetic support -- you'll have to get pretty savvy with the macro definitions though, to split the numbers from the units, do the math, and merge it back in -- and then that doesn't help solve the problem of wanting to merge 12pt with 0.8em.
I'll post another update here if I get the gm4 version working. I really like this basic architecture (a sh script executing multiple preprocessor commands, all executed by launchd), and fully intend to add this to my arsenal of tools as well. The strong point in the arch is that you can swap out the cpp part for anything, and the rest of the infrastructure would require only minimal changes to accommodate.
gm4 version done.
Dan, Dennis, and others...
You might want to check out my update to this -- I set it up using the gm4 macro processor, which ended up being as simple to use, and quicker to implement, than I had expected. See CSS Preprocessor - Take 2.
Again, still not your ideal language-that-understands-CSS ideal, but we may have to agree to disagree on that point. I just don't see the advantages inherent in that strategy. Do let me know if you actually use this in a project though; I'd like to hear how it worked out.
CSS GOTOs
Robert, thanks for all the comments, and yet another solution! I only have a moment for a quick reaction. You wrote:
I have a better understanding of wanting a tool that can understand CSS well enough to refer to information from other rules, but I'm having quite a bit of trouble seeing what it buys CSS developers. The way I see it, what you're asking for, if used in real life, will result in CSS that looks like spaghetti code - you're simply using named GOTO's.
This is a fair concern, and one I'll have to think about. It might mean trying some scenarios with an imagined syntax and seeing how it comes out. I might also argue that CSS already has a serious tendency towards spaghetti-ness. For the recent rewrite of this site's design, which is built within the PHP Template engine of Drupal, as well as in a separate publishing system I use for the articles side of the house, I know the CSS got a little complex. I split the CSS into separate files, and you can develop some concept of namespaces to keep things organized and to allow for variation of the same page elements on different kinds of pages. You do have to go to some effort to keep things clean. And it seems there can be side effects that make the built in CSS inheritance mechanisms not do what you need all the time.
I guess my point is that these ideas were hatched while in the midst of this site redesign, so I'm inclined to give them some credence, but it's certainly possible that you are right that basic string replacement functionality is enough to streamline the redundancies.
Best regards,
Dan
Create CSS using a template engine
Some of your ideas could be solved by creating CSS code using
a template engine. Usually template engines, e.g. Cheetah
(http://cheetahtemplate.org/) are used to create HTML, but
you can actually use them for creating anything, including CSS.
I've used Cheetah to create Postscript, PHP, XML and plain text.
However, I'm not sure how practial this would be.
This is not a crazy idea
Years ago I needed something like that for HTML (mainly to auto-create a dynamic menu - well, static for each file, but slightly different from file to file). I ended up creating my own text editor (with syntax highlightning, there is free code around for that) and added a simple precompiler to it. The syntax is somehow similar to PHP: with special tags I can define constants, use them, add if/then/else, include other files, pass "parameters" to these files (which makes them look like procedures) etc. I've decided to have special extensions for "uncompiled" texts like .uhtml, .utxt... and of course .ucss is possible, too. A simple click compiles the .uwhatever to a .whatever, replacing all constants, including other files after compiling them, too, etc. It's even possible to create projects with a simple command which compiles a file without including it. I've never published this editor/compiler because it is too premature, but I'm still using it from time to time, and I still find it useful to have such a precompiler for texts. So I really think this is not a crazy idea.
CSS Organization
As a complement to this thread, I later encountered this nice article in Digital Web Magazine about "architecting" CSS files to avoid the potential for the spaghetti effect discussed above. Worth a read if you're starting a new project and have not yet decided how to organize your CSS.
Dan


CPP? gm4?
If I were to tackle this problem, I'd probably just use the C Preprocessor (CPP) and use C-style #define's or #include's, or define a set of m4 macros. Then, each time I make a change to this enhanced stylesheet, I'd run
cpp styles.csse styles.css
and be done with it. It would be nice if that could be done automatically, and depending on what platform you're using (like Linux or OS X), you could set it up to run that command every minute, or when the file changes or something.
Actually, this is interesting enough that I think I'll try building this up tonight. I'll write it up on my blog when I have something to show for it.