The Constants Gardener

Published 19 years, 3 months past

This news is a little musty, but Shaun Inman updated CSS-SSC recently.  If you’re using CSS-SSC, you should definitely go grab the update.

“Hey, what’s CSS-SSC?” you exclaim?  Oh, I’m sorry.  It stands for Cascading Style Sheets Server-Side Constants.  Here’s Shaun’s initial example:

@server constants {
    linkColor: #AB6666;
    linkColorHover: #710101;
    }
a { color: linkColor; }
a:hover { color: linkColorHover; }

In other words, you can define your own constants in CSS.  This works because CSS-SSC is a preprocessor—it processes the style sheet before it’s sent to the browser, and turns it into something the browser can handle.  (Put another way, what arrives at the browser is a regular style sheet, with none of the ‘SSC’ information.)  Shaun offers more details in an earlier post.  CSS-SSC requires you to have PHP hanging about, and also to edit some stuff on your server, like .htaccess files.  You’ll also have to be careful about how you name your constants: use the constant name color, for example, and your CSS is going to go to a particularly mangled form of textual hell.

Personally, I’m both enthused and annoyed by CSS-SSC.  I think it’s a great solution: definitely one of the best, lightest-weight, easiest approaches to adding preprocessing to CSS.  I’m seriously considering putting it to use on ALA, in which I jumped through a few grouping hoops in order to get the fonts and colors just the way Jason wanted them.  Dropping back to constants would make life a bit easier—and would also simplify the whole “per-issue coloration” feature.  (Which I already have working, but via a large number of hoops, several of them on fire.)

I’m annoyed because it bothers me that Shaun had to create CSS-SSC in the first place.  There have been occasional requests for constants in CSS.  They get shot down every time.  “Use a preprocessor!” is the cry, and at first glance, CSS-SSC would seem to give credence to that response.  From my point of view, however, CSS should have had constants long ago, and what Shaun has done is proof.

The refusal to add constants as a feature of CSS has always stuck me as highly pointless.  Over the past decade, many people have expressed a need for CSS constants in a number of fora, and it’s a good bet many more have had the need without publicly expressing it.  Adding it to CSS would have done little to increase complexity on the implementor’s side; Shaun’s one-page PHP script (a good deal less when you remove the comments) proves that.  Adding it to CSS would have meant authors could just do it, without having to install anything else first.  Shaun’s made installation about as easy as it gets, but it’s still three or four steps more than should exist—and, for some authors, three or four impossible steps, due to their hosting situation.  And if you aren’t running a local web server, then you can’t test your CSS-SSC-enhanced styles locally; they’ll have to go to a web server first.

Because CSS still lacks, and will apparently continue to lack, a way to define your own constants, I’m really glad Shaun has devised this low-threshold solution.  I just wish that it hadn’t been necessary for him to do so in the first place.


Comments (34)

  1. I know I certainly could have done with CSS constants on many occasions.

    Although I did get good at remembering excessive hex codes…

    This would be useful for defining more colours than are defined in the spec (16 or so?)

    constants {
    myVeryOwnSpecialColourPink: #xxxxxx
    }

    div {
    color: myVeryOwnSpecialColourPink;
    }

  2. I know, I’m a jerk :)

  3. If you’re considering using this on ALA you might want to take a look at Scott Barron’s CSS Builder (more here, here, and here), which lets you write CSS in Ruby code.

  4. I’ve tinkered with the same topic in a slightly different syntax, but also using the at-rule for definitions; but my whole approach was to devise a system to use in development where I’d tweak and tweak and then generate the final CSS file when ready for production. Needless to say I never got past the “Wow, let me sketch this…” phase :-) (With a quick detour into “I must use XML+XSLT for this” – bad idea – XML’ified CSS gets ugly and verbose.)

    EX:

    @define {
    MainBgColor: #fadcad;
    PadSize: 3px;
    }

    ...

    body {
    background: var(MainBgColor);
    padding: var(PadSize);
    }

  5. One problem with Shaun Inman’s approach is, what happens if a user defines a constant in their stylesheet (or copied a whole set of constants from someone else) like so:

    @server {
    foo: #369;
    /* dozens of constants defined here,
    that's just one in the mix */
    }

    Then, later on, the CSS WG adds the keyword “foo” (like the keywords “large”, “small”, etc.) to a property: “bar”, and the author of the above stylesheet is unaware of this at the time.

    p { bar: foo; }

    However, later on (when that property and keyword is supported by browsers) the author wishes to make use of them, but fails to realise that because he’d defined that constant already for his pre-processor, it will be replaced by the server side script.

    Thus, the above style rule will be indiscriminately replaced by the preprocessor, leading to a potentially difficult debugging process (depending on the experience of the author). The constants to be replaced should at least be within a function, like this:

    p { color: -inman-constant(foo); }

    Secondly, where is the vendor prefix? @-inman-server {}? Even though it’s not actually being delivered to clients, it’s still a CSS extension and if this current @server version goes into widespread use on the web, then the CSS WG may have a difficult time defining their own @server keyword in the future without causing potential incompatibility issues. That’s the reason for the vendor prefix convention in the first place, no-one should be exempt from adhering to it.

  6. Lachlan: have you taken these questions to Shaun? Because I can’t change his scripts. Were I him and inclined to add a vendor prefix, I’d personally use @-ssc-server constants or maybe even reduce it to @-ssc-constants, in order to keep things minimally obtrusive.

    As for the problem of constants potentially causing future collisions, yes, that’s a concern. It’s a concern for anyone using any preprocessor, either of their own devising or of someone else’s, whether through PHP or Ruby or C or SNOBOL. This only deepens my frustration that the CSS WG hasn’t already defined a constants mechanism. Had they done so, we wouldn’t have to worry about these things.

    But honestly, I expect that anyone who goes to the effort of using a preprocessor, even one as easy as Shaun’s, is a) smart enough to pick names that have low collision probability; and b) mature enough to adjust their constants without much complaint should a future collision occur.

    Also, out of curiosity, what’s your rationale for requiring a vendor prefix on the CSS-SSC stuff when it’s all preprocessed out of existence, so far as the user agent is concerned?

  7. Eric, yes I commented on Shaun’s blog just after I commented here. I also suggested @-ssc- to him there. However, it is a vender prefix that supposed to indicate the vendor, not the name of the feature itself, but that’s not really all that important.

    While it is true that most users will pick names with a low collision probability, there will always be some users that don’t. However, users should not even have to think about whether or not their constant names clash with other CSS properties/keywords, much like users shouldn’t have to think about whether their ID attributes clash with IE. The system should just work. That’s the reason for requiring the functional notation.

    The reason for the vendor prefix is the same, though the consequenses of a clash will be much more harmful since a clash would require modification of the script and all stylesheets just to change the function name/@-keyword. That’s a problem that can be avoided with a vendor prefix. The other reason is really just a matter of principle. Why should one CSS tool be exempt from the requirment to use a vendor prefix for any extensions, even if, as in this case, their use is confined to the authoring environment, never to be exposed to the client?

  8. It’s worth mentioning the bandwidth and performance implications of server side CSS processing. Whilst CSS-SSC is a nice idea, it should be a client side technology, not server side. Or at least, the preprocessing should happen offline, not in PHP.

    I run a moderatly busy site at work and managed to speed it up enourmously and reduce bandwidth by making the CSS files static. All of a sudden HTTP’s If-Modified-Since worked again and the bandwidth usage dropped significantly. Also, because the file could be properly cached by a browser, the pages started to display quicker. It was a big win for little outlay.

    -Dom

  9. Dominic: it’s worth noting that Shaun made CSS-SSC smart enough to set and emit the proper headers to cache the processed version, so the processing hit of CSS-SSC should be basically nil, when averaged over all the accesses of the style sheet, and it will be cached locally by clients for the same reason.

    Yes, this sort of thing should be done client side; that’s what I was saying in the part where I explained why I was frustrated. Until it is, server-side is the only way such things can be done.

  10. I’ve argued for CSS constants before. I guess the reason they haven’t been implemented yet is that CSS then becomes a programming language. Why stop at just declaring the style and using it multiple times in a stylesheet? I would at least want to add and subtract to the style (were it a number).

    Just think how lovely a table might be if you were able to increment the background colour of each row by a minute shade. Or think of a hover colour that was a fixed percentage brighter than the text colour, no matter how many text colours you used.

    Maybe in CSS4 eh? :-)

  11. @Chris Hester: a while back I write code and an article about creating color palettes in CSS using PHP. It also includes accessibility checks to ensure that background and foreground color combinations have enough contrast to be readable. You can find it here.

    Regarding this CSS pre-processor, I guess I don’t see the point: why not just use PHP to create the CSS file?

    I can think of only two reasons:

    1. Your CSS will be produced by non-trusted users who you don’t want to have full access to PHP, or

    2. Your CSS will be produced by inexperienced users who might not be able to handle even simple PHP coding

  12. I think Constants are a great idea, and I’ve found myself mentioning that very concept to a couple colleagues in the past. The pre-processor idea is perhaps the best solution so long as proper Constants don’t exist. One key thing I would want to ensure is the caching. Any homemade CSS generator may not take into account the fact that CSS will be cached… How often will you really change the colours or fonts of your website?

  13. Here’s an idea I had a while back: I’d love to see an unholy marriage of PNG/GIF color indexing and CSS so I could switch a palette for any number of images by switching a central style sheet. Seems like CSS-SSC would be a good place to start with that. One could combine CSS-SSC with SVG on the server side to produce all the images for a layout, then switch the palette file to change the layout colors of the entire site…

  14. Pingback ::

    LANtastic :: Blog

    […] en k

  15. Trackback ::

    Joe's Apt.

    CSS Pseudo-Selectors

    Recently, I was quite happy to learn about Shaun Inman’s contribution to CSS maintenance sanity, Cascading Style Sheets Server-Side Constants. At the same time, I also share Eric Meyer’s frustration over the frequent knee-jerk “use a preprocessor”…

  16. My own site uses an on-the-fly preprocessor system for CSS, but I’m planning on taking it out; it just seems like a huge waste of resources to regenerate the same CSS file every time each page is accessed (modulo automatic client and/or server caching, which may or may not make it better). I intend to treat CSS as I treat HTML: as an output format, like PDF or PCL (laser printer) files, not an input format like word processor documents. In other words: generate the site using a templating system, pre-process it once, save the output to the webroot, and serve up plain HTML to anyone who wants it. Dynamic pages like blogs can do the preprocessing on the fly when required, but use a MAKE-style system so it doesn’t have to happen more than once per change.

    Well, that’s the idea… I have an awful lot of other ideas too, more than I have time for, usually.

  17. Sometimes I wonder what would have happened if we never had CSS, and it was JSSS instead, with everything being defined in terms of MS-style expression()s.

    You know, honestly, I think it would be pretty awesome. I mean, after all, LaTeX is “just a presentation language”, but the macros for looping, positioning, and content generation are extraordinarly powerful. It’s a much more mature system than CSS, but still… kind of wish we’d inherited some of that.

    On the other hand, if stylesheets had been too complicated, no one would ever have used them. It’s not like keeping that stuff out and giving us floats and negative margins instead really made it easier conceptually.

  18. Pingback ::

    Robert’s talk » CSS constants

    […] r manageability to edit all these values in one place I aggree with that, and I think, as does Eric Meyer, that constants in CSS is a good idea and that they shoul […]

  19. This post inspired me to make a demo using CSS generated from PHP:

    CSS Gradients Demo

    There’s one other server-side CSS approach people might consider for constants and variables, and that’s XSL-FO. Or has that been abandoned due to its complexity and verbosity?

  20. Trackback ::

    Andrew Beacock's Blog

    Constants in CSS – it’s like waiting for a bus

    I’m more of a server-side programmer really, and don’t deal that much in client-side stuff like CSS and JavaScript, but I try to keep an eye on what is going on in those areas as they tie so closely to the backend stuff.

  21. Pingback ::

    torresburriel.com » CSS-SSC: preprocesador de hojas de estilo

    […] uilo. Resulta que mirando otra cosa en el weblog del gran Eric Meyer cuando he visto esto: The Constants Gardener.

  22. I’ve recently been using the C preprocessor to implement constants in CSS files. For example, to define a color scheme, I insert the following lines in my .CSS file:

    #define CLIENT_FG #123456
    #define CLIENT_BG #987654
    #define CLIENT_TXT #012

    /* I can then use statements such as: */
    body { background-color: CLIENT_BG; color: CLIENT_TXT; }

    I have a one-line UNIX shell script named ‘ppcss’ that handles the processing:

    cat $1 | cc -E – | grep -v ^# | grep -v ^$

    By convention, I name my CSS files *.CSS for the “raw” files (those that contain preprocessor statements) and *.css for the “clean” files (those that contain pure css code, after preprocessing). I edit the .CSS files, then run the command

    ppcss foo.CSS > foo.css

    to generate the “clean” css file. Note that this script strips comments and blank lines as well as preprocessor statements (which is OK, because I don’t need the comments in the file when I upload it to the web server, and the fact that the comments never have to be downloaded to the user’s browser make me feel better about including lots of comments in my css files).

  23. An amendment to my previous post: To prevent the C preprocessor from barfing on CSS files containing unqualified IDs (things like “#navbar”), you must do two things:

    1. Put a space (one or more) before the ‘#’ in the ID’s definition. So,

    #navbar { ... }

    will cause trouble, but

    #navbar { ... }

    will be OK.

    2. Change the ‘cc’ command in the shell script to invoke “traditional” C preprocessor behavior (which ignores preprocessor commands that don’t begin in the first column). This will vary from compiler to compiler; on the Gnu C compiler (gcc) the correct command is

    cat $1 | cc -E -traditional-cpp - | grep -v ^# | grep -v ^$

    Sorry for the inconvenience. As it turns out, I seldom use unqualified IDs, so I just noticed the problem.

  24. Sorry again, folks. The examples above don’t make much sense because the poster deleted a leading space. Let’s try this:

     #navbar { ... }

    will be OK. [In case this doesn’t come through correctly either, there’s supposed to be a blank space before the ‘#’ in the line above.]

  25. Inasmuch as CSS already supports constants or reserved names such as font names or colours then it would seem logical to extend this to support user definitions as this improve legibility and maintainability. Without it we are forced to jump through the hoops of server or client side procedural programming for essentially declarative presentation.

    I’ve been working in HTML for years but am only just making the switch to CSS (thank you Eric for an excellent book!). I have come across a number of areas where I am going to have to resort to programming where I might hope CSS to help me: rotating images and setting the navigation style for the active page. Faced with the prospect of two different levels of programming (server-side substitution for the image rotation and possibly Javascript for the active navigation) I’ve been asking myself whether it wouldn’t be easier to program everything in one level. For generated pages CSS should be easy to use and integrate otherwise it may be easier to ignore.

    I agree CSS should not become XSLT and it should not become a full programming languages but support for dynamic, context-driven values can be included without this.

    ie. a:current – highlight a navigation item for the current page without excessive and possibly tricky use of ids and classes;
    {background-image URL:random(image1.gif, image2.gif…);}

    Furthermore, pushing this into CSS gives both the designer and the user more control of what is seen.

  26. Pingback ::

    Extra Hot » Defining CSS Constants Using PHP

    […] r interesting technique pointed out in the discussion is the CSS-SSC work by Shaun Inman. Thoughts by Eric Meyer. read more | digg story

    […]

  27. This is great. Shaun Inman is truly the master of web development.

  28. Pingback ::

    Anne 2.0 » CSS Makes Me Cry - Three Reasons

    […] ors. Sure, I can stick comments all over the place but that’s no substitute. You can do constants with a CSS preprocessor, but I want it baked into CSS. 2. No si […]

  29. The server constants solution is great if I work and test directly with/in my cms – BUT:

    Is there a way (in PHP – sorry, I’m not a PHP expert!) to explicitly create/write the output/expanded css file (= css file after the substitution of the constants) on my disk. So I would be able to continue with testing the layout of my website (as I did before with my html-template + my expanded css file) separately in my favorite WYSIWYG-HTML-Editor (z.B. DreamWeaver) + Browser (without PHP!). After the layout testing I would put the files (html/css) separately in my cms backend… (as I did before).

    Now (with the PHP server contants in the css file) I am not able to test my html layout any more… !?

    Thank’s for help.

  30. Time and time again I wish there were standard CSS constants. Why, oh why hasn’t this happened yet? What is the reasoning behind this refusal, who refuses it, and why do they have they have a career/say-so in something they obviously don’t know anything about? They must have an IT background…

    Anyways, regarding post #2: agreed (kidding).

  31. Pingback ::

    CSS Pseudo-Selectors • Blog Archive • Joe’s Apt.

    […] maintenance sanity, Cascading Style Sheets Server-Side Constants. At the same time, I also share Eric Meyer’s frustration over the frequent knee-jerk “use a preprocessor” responses to proposals such as (and […]

  32. Try p4, the Perl based macro processor. Works great for CSS.

  33. Please check out CSSPP