CSS Constants: A Rant

by David Gauer, 2007

CSS needs constants and it needs them right now. I'll be damned if I've yet heard anything make me think otherwise. If you have a reason I don't cover below, let me know so I can update this page.

The Problem

Let's say you have the following extremely simple CSS document:

a { color: #ff0000; font-weight: bold; } h2 { color: #ff0000; margin: 2em; }

A two-line CSS file is not hard to manage, but already we can imagine a problem. We have explicitly called for a red (#ff0000) color twice in our document. If we decide to change all of the red in our website to blue, we have to do replace each #ff0000 with #0000ff. Again, with just two instances, this is not a big deal. But with a little imagination (or if you've ever managed a large site, you already know), you can see why this would be a tedious thing to do if it appeared hundreds of times.

I would argue that in addition to having to replace the hex code in multiple places when changing, it is also a major pain in the ass to have to write (or remember or copy-and-paste) this same value over and over again. This happens a lot in the creation of a CSS document. And not just to newbies, either. Don't believe me? Try CSS color constants in Google and see what sort of people have this problem. (Answer: skill levels ranging from newbies to people who have authored books about CSS)

The same principle can be applied to things like padding, margins, background-images, fonts, etc:

a { font-family: "Sweet Font"; more styles... } h2 { font-family: "Sweet Font"; more styles... }

It is quite natural to want to re-use the same bits of style for multiple element or class definitions.

Obviously, if two definitions are exactly the same, they can be defined together:

a, h2 { styles...}

But as soon as a single property in one definition is different, it must be completely copied and the difference applied:

a { styles...} h2 { styles... the one different thing}

You can imagine how many instances of this sort of thing you might find in a large, complex web site and how painful it would be to manage it.

This is not a trivial problem, and many excellent articles have been written about the problems of replication in CSS.

The Solution

While it is not a magic cure-all for the hairy problem of replication, named constants would be a powerful tool of massive immediate benefit to CSS users everywhere. Let's see how that might address our problem. Here is some syntax that I just pulled out of my ass to illustrate what constants might look like as applied to the first problem example:

$hawtColor: #ff0000; a { color: $hawtColor; font-weight: bold; } h2 { color: $hawtColor; margin: 2em; }

Now when I want to change the color from red to blue, I just change the definition of $hawtColor and I'm done.

Let's see another, slightly more complex (and thus, useful) example:

$color: #ff0000; $neatStyle { padding-left: 1em; margin-top: 3em; background-color: $color; } a { $neatStyle more styles... } h2 { $neatStyle more styles... }

This should be pretty easy to follow, but here's the breakdown:

  1. Define the named constant $color as #ff0000 (red)
  2. Define $neatStyle as a list of style properties (including a background-color set to our handy $color constant)
  3. Apply $neatStyle to the a tag along with whatever other styles we want
  4. Apply $neatStyle to the h2 tag along with whatever other styles we want

As you can see making a change to the padding-left of a and h2 need only be done in one place, $neatStyle. Imagine if we did not have named constants. Imagine your CSS file (or files, plural) was enourmous and contained a hundreds of repeated bits of style and you needed to change a dozen of them. Unlike a simple color change, you will probably not be able to use Search and Replace to correct the problem. Instead, you might spend a good part of the day finding the separate copy of the style and making the changes manually.

Constants Would Be So Easy To Implement...

The above named constant syntax seems pretty workable to me. The rules appear to be simple:

I'll even throw in a bonus rule:

I think it's easy to understand and handles everything I can think of. But this was created in a couple minutes as an off-the-cuff example. Just think how much better it might be if somebody smarter than I put some real thought into it...

At it's most basic, a feature like this would be incredibly simple to implement. Just grab the definition for each name as you encounter them in the CSS source and then parse them in place wherever they are called for later on. If a name is called for before it is defined, nothing happens. I could write that code in my sleep. That there are so many CSS pre-processors out there written in PHP, Perl, and other languages shows that this task is not only do-able but that people really want this feature!

Now, to make this feature better, and support the idea of CSS as a non-procedural presentation language, we should allow the named constants to be refered to in the style sheet before they are defined. This could be easily implemented by having the constant style be retained as a separate style in memory and applied when used by a style that references it. Slighly less trivial to implement, but not brain surgery, either. It's certianly nothing compared to the task of implementing CSS in the first place!

Obviously if a style referencing a non-existant constant is used in HTML, we do nothing, just as if a regular non-existant CSS style had been called. Again, these are not difficult rules to create.

So Why Don't We Have Them?

You might be wondering, as I often have, why we don't have any semblance of named constants in CSS. The reason is called the CSS Working Group (CSSWG). The CSSWG doesn't want us to have constants and so we don't. Nevermind that people who actually use CSS on a regular basis want this feature. Nevermind that most of us have resorted to all sorts of arcane, complex, or downright dire work-arounds for this pointless lack. Nope, these folks don't want them, and that's that.

Do they have reasons? Sure they do. But I'll be damned if I've heard a convincing one yet. The CSSWG mailing list archive contains some pretty typical responses to the constant (pun!) request for constants. You can find many more as comments to blog posts and in forums through a simple Google search.

"It Would Be Difficult To Implement"

From the CSSWG mailing list (www-style):

There are many different ways constants could be used. A proposal that would support all of them would be difficult to specify and difficult to implement.
- L. David Baron, Aug 27, 2007

From a Slashdot interview:

What if aliases are defined in one style sheet and referenced in another -- should that work? If so, what if the first style sheet isn't available? For CSS1, the downsides of aliases were considered more significant than the benefits.
- Håkon Wium Lie, June 23, 2006

In other words, "it was too hard, so we didn't bother." That didn't stop them from creating a huge number of other very complex and very difficult-to-implement features. Also, note that hundreds (thousands? who knows?) of developers have addressed this shortcoming of CSS by implementing homebrewed CSS preprocessors. The difficulty excuse simply does not fly for me.

"They Would Make CSS Harder To Learn"

For some reason, I see this a lot. I genuinely don't understand where this attitude comes from. Sure, not everyone is comfortable with programming. And constants are often seen as being in the domain of programming. But I think it's outright laughable to suggest that understanding $color: #123456; is even in the same league as attempting to create a non-trivial page layout in pure CSS.

I think that constants could actually aid in the readability of CSS documents. Page after page of repetition and bare color hex values could be replaced with well-named constants. Huge website CSS documents could actually be edited by mere mortals!

Also, even if the concept is difficult for some, I don't understand why that would be a valid reason to deny it for those of us who understand and want the feature.

"Use Multiple Classes as Constants"

A feature of CSS that is often used in a manner to suggest constants is to define numerous classes and apply them as needed to the HTML markup.
CSS:

.font1 { font-family: "Sweet Font"; font-weight: bold; } .note { background-color: #FFFF00; } .warning { background-color: #FF00FF; } .special { text-decoration: underline; }

HTML:

... <span class="font1 note special">Free cow!</span> <span class="font1 warning special">Arrgh!</span> ...

I have absolutely nothing against using multiple classes like this. But I can say that having built a medium-sized commercial website that used this technique, it pretty much sucks after the first dozen classes. The tendency is to end up repeating strings of multiple class names all over your HTML. And after a while it can be difficult to remember if you used "headerFont errorBox warning" or "headerFont errorBox highlight".

This technique does work. And there are all sorts of reasons to style a tag with multiple classes. But you better have a really good naming scheme and/or a really good memory to put it to use. And that's kind of my point. It works, but so does repeating #FF0000; a hundred times in your CSS document. It works, but it's not easy or fun. And it makes the developer remember things when it should be the computer that has to remember them.

<span class="headerFont errorBox warning">Dangerous Text</span>

...is me having to remember something.

$headerMargin { margin-top: 5px; margin-bottom: 10px; } ... .millionthElement { $headerMargin; font-weight: bold; }

...is the computer having to remember something. I can tell you which is more likely to fail!

Probably my strongest argument against <span class="headerFont errorBox warning">...</span> is that it brings us back to the days of putting all sorts of display information into the markup. It's better than a <font> tag, sure. But not as good as it could be. And isn't getting away from that sort of thing kind of the whole point of CSS in the first place!?

"Group Selectors To Apply Common Styles"

One approach is to apply a style to more than one selector and thereby avoid repetition. Say we start off with this:

h1 { padding: 2em; margin: 3em; color: #FF0000; background-color: #000000; } h2 { padding: 2em; margin: 3em; color: #FF00FF; background-color: #000000; }

This can be re-written as

h1, h2 { padding: 2em; margin: 3em; background-color: #000000; } h1 { color: #FF0000; } h2 { color: #FF00FF; }

where both elements have been grouped to apply all properties except the one that is different, color. color is then defined separately for each.

In short examples, this method is the most appealing. It seems to solve the problem. Unfortunately, in real-world applications grouping quickly breaks down as you find yourself grouping obscene numbers of selectors together from all over the place.

span a, div#footer .copyright, div#footer .placemat, li b.note, #clownTheme h1, #clownTheme h2, div.openPanel a, div.openPanel span b { padding: 2em; margin: 3em; color: #FF00FF; background-color: #000000; font-family: "bitstream vera mono", monospace; font-weight: bold; }

Bah! While it's certainly nice not to have to re-write that lengthy style for each of these separate elements, can you imagine having to support this nightmare? You would have to do a Find in your text editor just to locate the style, and that's assuming you knew what you were looking for. Even then, you might get several hits for other styles being applied to that element before you found the style you were looking for.

Also consider what would happen if just one single element from the above list needed to have a different color property. Let's say it's the li b.note selector. Well, we could write an exception for that selector below the big style like so:

li b.note { color: white; }

But that's just making a mess even worse. Good luck trying to figure out what li b.note's color is later on.

"Write/Use a CSS Preprocessor"

What if I

The thing that really irks me about people proposing the existance of server-side solutions as the reason we don't need CSS to be fixed is that they actually reinforce the fact that CSS is lacking something in the first place.

"It's Too Much Work For Low-Powered Devices/Browsers"

Frankly, unless somebody can tell me why I'm wrong, I think this argument holds the least amount of water. Any device that can render HTML and apply CSS styles to the DOM is not going to have a problem with constants.

"Cascading Solves All Problems"

Cascading (the C in CSS) is obviously one of the primary traits that one should plan for when creating a web site. Cascading allows us to do cool things like:

body { font-family: "Sweet Font"; } h3 { font-family: "Lame Font"; } div#snakes h3 { font-family: "Snake Font"; }

which styles the entire document with the Sweet Font except for h3 tags which get the Lame Font, unless they are inside a div with the snakes id. Those get the Snake Font.

Cascading is one of the truly great things about CSS. It does a lot of work on our behalf. But cascading alone simply cannot address the needless repetition in all but the background-color in the h1.better and h1.best classes in this example:

h1 { font-family: verdana, fantasy, monospace; color: black; } h1.good { font-family: "times new roman", times, serif; color: #FFFFFF; background-color: #FF0000; } h1.better { font-family: arial, sans-serif; margin: 4em; padding: 3em; color: #FFFFFF; background-color: #FFFFFF; } h1.best { font-family: arial, sans-serif; margin: 4em; padding: 3em; color: #FFFFFF; background-color: #FF00FF; }

You might suggest something like enclosing the .better and .best h1 tags in a common div tag like so

<div class="better-best"><h1 class="better">...<h1 class="better"><div> ... <div class="better-best"><h1 class="best">...<h1 class="better"><div>

Which would allow the sharing of much of the styling information in the CSS like so

div.better-best h1 { font-family: arial, sans-serif; margin: 4em; padding: 3em; color: #FFFFFF; } h1.better { background-color: #FFFFFF; } h1.best { background-color: #FF00FF; }

And you would be right. But wait a minute, let's back up a second. Wouldn't the "Content Vs. Style" CSS purists flay me alive for putting non-semantic markup in my HTML for no other reason than to share some style information? Sure they would. And they would be right. I shouldn't have to alter my well-formatted and semantically-correct HTML source one iota to avoid repetition in my CSS.

"<Insert Strawman Argument Here>"

For some reason, any time the subject of CSS constants comes up, somebody has to throw up all sorts of statements about how once you start down "that road", you'll end up with scripting in CSS with security problems, memory problems, etc. I don't understand why this conclusion is jumped to. Seldom has any sort of scripting even been mentioned up until that point.

Now, actually I would love to see some programmatic elements in CSS. I have this strange belief that computers exist to do work for humans, not to enforce arbitrary content vs. display philosophies. But that's not what is being asked for when I say that I want some constants! Constants are not variables. They are not loops. They are not if-then-elses. They are not Turing-complete. They are a simple mechanism to avoid needless repetion. How could that ever be bad?

No matter what my other desires might be and no matter what my many other gripes about CSS might be, believe me when I say

I just want constants.

So leave your strawmen at home. They're not doing anyone any good.

In Conclusion

I do not understand how constants might not be in keeping with the design philosphy of CSS. After all, CSS is itself a big system for the defining of constants to be later applied to markup. Repetition, no matter how it rears its ugly head, is a bad thing. Repeating big enough amounts of anything is error-prone, tedious, and not in keeping with anything that even remotely smells like a good practice.

And here's a last parting thought on the subject: Let's say I'm wrong about all of this. Maybe I'm really just not smart enough to format my HTML and CSS "the right way" so that everything works like a dream. Guess what? Judging the amount of requests for constants, there are a lot of others who aren't smart enough to "do it right" either. So can us idiots please have some constants so our little brains can make CSS that doesn't suck so much? Thanks.

Conclusion Part II (October 2012)

So I wrote a comment on a Hacker News article a little while back that I think neatly summarizes how I feel about CSS now. As you can see, five years later I'm as dissatisfied with CSS as I was when I wrote the above rant:

CSS was clearly designed with typography and text layout in mind - and it works wonderfully for that purpose. But it was not created flexibly enough to be well suited for anything else. You CAN make graphical interfaces with it (and we do, because we have to). But it's all hacks.

I think the browser inconsistencies are as frustrating as they are because doing seemingly "simple" things in CSS requires using advanced CSS features in boundary-pushing ways (this wonderful arrow box app is a perfect example). Browser support has to be EXCELLENT before certain simple layout things are even possible. Imagine a CSS that supported things like "vertical-align: center". That's a CSS that wouldn't NEED to have its boundaries pushed to the limits and the rough edges of browsers wouldn't rankle nearly so much.

It never ceases to amaze me how quickly people jump to defend CSS as if any criticisms imply that the author thinks we'd be better off back in the days of deeply nested tables. But the sad fact of the matter is that some things really were easier and more dependable (and in some cases, WAY more so) with tables.

And when you really think about it, that's just pathetic. We should be able to do better.