Why is CSS so hard? It is verbose, repetitive and cumbersome. At the heart of the matter, CSS has not been designed as a language. As such, CSS has no ways to express things elegantly. It is all hard coded from beginning to end.
I had been thinking about this for a while, and was considering coming up with some sort of CSS generation language. Then, as these things happen, I read CSS Repeats Itself and everything became clear.
The problem
The problems with CSS I would classify as:
- No variables. There is no way to set and re-use variables in CSS. This means that to make a width or height or margin (or anything) consistent, you just have to set the same value everywhere. To make it worse, if you want to change the value, you have to change it everywhere. If values collide, your global replace is going to break something. If values are in different stylesheets … well … good luck!
- No expressions. There is no way to say “this equals twice this plus that” in CSS. You have to figure it out by hand and hard code the value. If one of your values change, you better remember what to re-calculate (after changing all the instances by hand, that is).
- No includes. There is no way to include a CSS file within another CSS file. This must be done by importing multiple stylesheets in the final (X)HTML document. This hides dependencies between CSS files and prevents reuse.
- No inheritance. There is a sort of broken implicit inheritance in CSS, but it is totally opaque (to me, anyway). I would rather express inheritance explicitly, rather than by the imposition of obscure ordering and specificity rules.
You can sort of see why this happened. Without variables, expressions make less sense, as do include files. I think (true) inheritance was considered out-of-scope :p
Towards a solution
In CSS Repeats Itself the challenge was to solve this with XSLT. Well, I don’t know XSLT, so that is not an option. Also the implication was that this would be an on-the-fly thing, though I am not sure if that was specific to a specific server or a suggestion for a “grand new Internet architecture”.
I was more interested in a solution for a developer like myself, so my solution was always going to be in the world of build systems (where I believe all such things belong). Looking at the example it struck me that most of what we want to do we already have the tools for (surprise, surprise). So I took about ten minutes of my time, and reworked a project using:
- cpp
- make
Not quite the sexiest set of tools now-a-days. But they get the job done, and they work in my environment! (Always a plus). I would hate to think of a development environment that didn’t have this sort of capability, but I am sure they exist *sigh*.
My solution
This is a quick example I cooked up, based on the example in CSS Repeats Itself. It is more to show what could be done, than what you should do.
Makefile
file.css : file.pcss
cpp -x c -P -C $? -o $@
I have created the “pcss” file extension, meaning “pre-processable CSS”. So file.pcss is our source file, from which we build our CSS file, file.css, as part of our system build. For a well setup project, this should not introduce any wrinkles. The only issue I can see, which is hopefully minor, is that projects without *any* build phase (e.g. PHP projects) may not have a nice place to slot this in.
The command breaks down as follows:
- cpp is the C pre-processor. It is designed to work on “C”, but we can bend it to our will.
- -x c treats all files as “C” files, which is just as well because it has no idea what a .pcss file is.
- -P turns off ‘#line’ commands which would ruin our file.
- -C keeps any comments that might be in our code, though we might want to turn this off.
file.pcss
#define LC 200px
#define RC 150px
#define WIDTH 550px#include “3col.pcss”
3col.pcss
body {
min-width: WIDTH;
}
#container {
padding-left: LC;
padding-right: RC;
}
#container .column {
position: relative;
float: left;
}
#center {
width: 100%;
}
#left {
width: LC;
right: LC;
margin-left: -100%;
}
#right {
width: RC;
margin-right: -RC;
}
#footer {
clear: both;
}
The make command creates file.css:
body {
min-width: 550px ;
}
#container {
padding-left: 200px ;
padding-right: 150px ;
}
#container .column {
position: relative;
float: left;
}
#center {
width: 100%;
}
#left {
width: 200px ;
right: 200px ;
margin-left: -100%;
}
#right {
width: 150px ;
margin-right: - 150px ;
}
#footer {
clear: both;
}
I have made the three column layout an include file, as it may be re-used for many projects. The parameterisation of the layout means not only does it remain consistent when it is changed, but every project can use different values while using the “same code”. An obvious advantage to any programmer, but a bit lost in the CSS world.
Summary
The solution above is simple and should be easily achieved in most development environments (so I assert without proof). This solution:
- Solves the variables problem by using macros to define constants.
- Solves the include file problem through the preprocessors “include” function.
- Partially solves the expression problem. We still cannot use expressions, but we can use macros to put the each hard coded value in one sensible location (i.e. with their related variables).
- Does not solve the inheritance problem. We can make some things better, but the solution may be as complex as the problem, and we still have to contend with CSS’s internal model.
Caveats
When I generated this example, I noticed (belatedly) that these is a problem with it. In file.css one of the expansions evaluates to “- 150px ;“. This is because the C preprocessor inserts space around macro expansions (for reasons which are too mind bending to go into here). This is a problem because I am not sure (i.e. I don’t know) if this is going to be alright or not. “C” is pretty robust about such things; I doubt whether CSS is so robust. This means that even using this solution, you have to be careful to avoid such constructs. You will need to do something (admittedly sub-optimal) like:
#define RC 150px
#define NEGRC -150px
I have not tested this extensively, and suspect there may be other cases that make CPP barf! Also in my research after writing the bulk of this article (see below) I found much concern about id tags (e.g. #blah) being mistaken for cpp directives. This is possible, if the id formed a reconizable directive. AFAIK unrecognised directives are passed through unchanged, which is what we want.
Postscript
While following up the inserted whitespace problem, I came across Using a C preprocessor as an HTML authoring tool, which is the same thing for HTML (all the way down to the same CPP arguments).
Then I thought; well, this is all pretty obvious, someone else might have done something similar … and they have.

3 responses so far ↓
1 Eric Meyer // Oct 7, 2006 at 4:53 am
CSS might be limited, clumsy, and repetitive compared to some programming languages, yes, but compared to HTML-based layout? It’s a paragon of cleanliness and simplicity.
Not that it’s perfect, of course.
Variables are one of those things that I’d love to see added to CSS, but there are apparently some considerations on the browser side that complicate things. Same with expressions. The two together make things worse. I’m not a browser vendor, so I can’t state this with authority, but that’s the impression I’ve gotten from browser vendors.
Oh, and there is something of an include in CSS: @import. You can use @import in a style sheet to pull in another style sheet, and you can have multiple @imports in a single style sheet. The limitation is that any @imports have to come at the beginning of a style sheet, rather as I understand includes work in C. (Don’t know C, so I could be wrong there.)
I think in the end your solution is interesting, but for the vast majority of web creators, too complicated. I’m no slouch in the computer world, but using ‘make’ and the like is not part of my skill set. The same is true for the large majority of web design experts and practitioners I know. That’s exactly why I’d like to have variables added to CSS: they would provide the functionality you’ve shown without requiring command-line expertise.
As for inheritance, I think you’re hitting a wall lots of programmers do: inheritance in CSS refers to how style effects propogate down the document tree, not however it operates in an object-oriented programming language. Same word, different effect. (I think. Again, not really a programmer.)
2 Streamlining CSS - Part II | Phil Wallach // Oct 9, 2006 at 3:01 pm
[…] Eric Meyer’s comments on Streamlining CSS sparked some further thoughts (always a good thing). […]
3 phil // Oct 9, 2006 at 3:10 pm
Eric
Very interesting and illuminating. It is good to have another perspective.
You were correct to cast my criticisms as being from a programming language perspective; that is exactly that they were. The post was my reaction to trying to master CSS over the last 6 months. My frustration has been the lack of expressivenesss I expect in a programming language. Which is not to say I have not found CSS a good and useful tool for styling webpages; I have found it great. My comments spring from wanting more, from seeing the better in the good.
I also take your point with regards to inheritance. CSS is a specific tool for a specific purpose. Those like myself who come to it from the point of view of programming languages, may misunderstand or misuse the features of CSS, and then blame the product (boy I bet that never happened before). I would not be surprised if inheritance, such as it exists now in CSS, is very useful to those who know it well.
Nevertheless, I still believe that some form of (object) inheritance would enhance the expressiveness of CSS, rather than how it works or what it does. From your comments I understand that an important issue is not whether this improves CSS, but whether or not this over-complicates CSS and makes it unuseable by its core consitituency - designers.
Thanks for the pointer on @import, I will follow that up. (As an aside, the C preprocessor has no limitations on where include files go; it is the contents of almost all include files that require they appear at the beginning of the file).
Leave a Comment