CSS-SSV
Update
Check out CSS Server-side Constants for an improved, “more-better” stab at the same idea.
A few of the comments on Andy Budd’s most recent article got me thinking again about variables in CSS. Remember Jeff Croft’s first stab at the idea? His approach didn’t sit well with me for one reason: it required embedding PHP in a CSS file. Even with PHP short tags turned on, inline echo statements are tedious to type and make it difficult to quickly scan the CSS. In the year since Jeff’s post I’ve learned some of the finer details of PHP, .htaccess and regular expressions. When I encountered the discussion on Andy’s site today my brain connected the dots and an hour later I had a working implementation of CSS server-side variables.
CSS-SSV hijacks the syntax of at-rules to isolate variable definitions. Variable names and their values are defined like any other CSS property. The goal was to make this as easy-to-use and native-looking as possible:
@server variables {
variableName: variableValue;
}
This is how variables are embeded in the CSS:
selector {
property: variableName;
}
Take a sample (simple) CSS file:
@server variables {
primaryLinkColor: #AB6666;
}
a {
color: primaryLinkColor;
}
With CSS-SSV the browser would receive the following:
a {
color: #AB6666;
}
Interested? Good. Download the CSS-SSV replacement function (I know, I know, I’m really pigeonholing myself here—another replacement script from Shhh-yawn Inman) and upload it to your CSS directory. In that directory create a file called .htaccess
if one doesn’t already exist and add the following code to it:
AddType application/x-httpd-php .css
php_value auto_prepend_file /local-path-to-your-css-dir/css-ssv.php
Change local-path-to-your-css-dir
to the appropriate value. Your local path can be easily found by checking $_SERVER['DOCUMENT_ROOT']
in phpinfo() or by echo
ing it in a test page. Then tack your CSS directory name on to the end. That’s all there is to it. You can start using the @server
rule as described above.
In CSS-SSV’s current form, you can’t use variable names that might otherwise appear in your CSS, like padding
, em
, or part of an image name or path. Variable names that contain those, like mainPadding
or defaultEms
, would be fine.
036 Comments
I just don’t really see the use of variables in CSS, mainly because it’s Cascading and HTML has classes that can be combined.
Basically, that totally eliminates the need for variables, which would complicate the language a lot more than I find necessary.
Cascading -> stuff inherits Stuff that doesn’t inherit? Classes! Combine them in your markup, it’s okay, the attribute was meant for that.
Just a sidenote, for those under php-as-cgi (rather than module) auto_prepend_file and auto_append_file are not available and you’ll have to look toward includes instead.
Sure Faruk, in an ideal situation—but what if your code is locked up in a legacy CMS and you don’t have the ability to add an arbitrary class? Or if the same colors/font-families show up in multiple places in your CSS like in the following sample?
Imagine that multiplied by even a handful of elements and properties. There’s clearly a need in certain, unenviable but uncompromising situations.
fricken sweet. This is a nice approach. Crappy about the .cgi issue as a number of hosts run PHP that way.
You scare me. Far too clever for your own good. It’s not natural :-)
Shaun,
Agreed, there are circumstances where this would prove handy. However, I still don’t see it as a missing feature of CSS.
First of all, it would bloat CSS. I’m reminded of PHP and its incredible function-bloat. CSS can do what you want it to do without your (pretty crafty, I must say) little script.
Also, examples such as yours above can still be taken care of easily:
Thanks to the nature of Cascade and Specificity that are part of CSS, my example does the exact same as yours.
Effectively, almost all redundant code can be taken out of CSS using what’s possible already. It’s easy to think like a programmer when dealing with CSS (I’ve done it myself often enough) but CSS is a different type of language. It’s not a programming language at all, it’s a presentation language. It has what we need, it just has them in a different way.
Would CSS benefit from having variables? Personally, I doubt it. Right now, CSS is 100% straightforward. Variables would change that, making it even more difficult for newcomers to get a hang of it.
Thanks Faruk, but your example is just a further simplification of my already simple example. That approach, while efficient and handy in certain situations, does not scale well. Especially on a larger project with multiple producers touching the same CSS.
There seems to be a basic underlying problem here: browser caching of stylesheets. In fact, it all but elimates this approach since they’re really not variables anyway.
You’re much better off doing “fake” variables:
font-family “Georgia”, “Times”, serif; /* var1 */
Doing this a simple find-n-replace works wonders.
If you really wanted this functionality in the first place… why not make your CSS file a PHP file and send the correct headers and such?
I think you’re confusing the purpose of the variables here, Kyle. It’s not meant to be a dynamic value that’s going to change. It’s a value, defined once, that is used in multiple places. In which case caching works for us as it always has. Perhaps a better name would have been CSS Server-side Constants.
And I explain in the article why I don’t just embed PHP in the CSS file.
Bit of a hog for a stylesheet, isn’t it? Don’t get me wrong, lots of times I find myself preg_match-ing articles in the newspaper as I read them, but this really seems like a pound of server overhead for an ounce of remedy. I asked myself before commenting if I was just demurring out of some silly sense of encroachment, but I think I’d put this in the folder as a nuclear option, only to be used in a case where someone wants me to make the proverbial chickensalad out of the you-know-what.
Now Josh, that’s a valid criticism for which I have no solution.
I guess you have to decide for yourself if the overhead is significant enough given your own, unique hosting situation.
Shaun-
Nice work, as per usual. Clever method. Another problem with the original technique I suggested a year ago was that it effectively negated the browser’s caching of the CSS file, which is one of CSS’s great benefits to begin with.
I presume this would have the same downside?
In the past to accomplish this, I’ve used a simple variable mapping in the CSS, such as:
(You can really pick your own namespace here, but it helps to have a clear symbol marking. You could also do something like
/*-VARNAME-*/
)Then, on the PHP side:
The concept was actually based off of the core template engine used in phpbb. You can vary it slightly by changing the way the templates are formed, but overall, it lets you put view logic into css.php (via variable assignment) and keep the display side of the CSS really pure.
This also is good for those who might have problems with their .htaccess
Shaun, forgive me if I’m being a bit ignorant… I just don’t see how saving it as a PHP file takes any extra time. A simple:
Would accomplish the same thing you were referencing, no? Granted, there is an added $ prepended to variables, but I don’t consider this much of a hinderance to anyone familiar with PHP.
The whole caching problem could be solved with a simple cache header, right? Isn’t it as simple as that to make browsers cache your pseudo CSS file just like one normally would?
I like this idea. It took me a bit to warm up to it, mostly because I didn’t understand what was going on and what the advantage was. Basically, we love CSS because we can change one file and have site-wide effects. Now, with ideas such as this one, we can further abstract the redundancy in a CSS file to this variable method.
If I decide to switch from Sans-Serif to Serif fonts, I only have to change it in one place rather than 15. That is cool.
Shaun,
Yes, you do have a point there indeed: scalability. However, (nope I won’t give up that easily ;)) I will ask you this: will it really be beneficiary to the end result when you use CSS variables through multiple files, on which multiple people work? If several people are working with the same file or files, wouldn’t it actually be counter-productive?
“What’s this variable mean, again?”
I mean, logically, the variable names are shorter than the content they’re to represent, otherwise, what’s the use? But will all producers know what’s meant with each variable?
Still, you have a good point about scalability. :-)
Faruk: I would say it would be even more beneficial in that case. Let’s say Joey Baggadoughnuts is plundering through a CSS file and he decides he wants to change an “18px” to a “24px” in order to increase his gutter. Little does our greasy little friend know that he is actually creating inconsistencies with other gutters set through the site. If the variable was stored as “gutterball” instead, he can look through any other CSS files for this variable and see exactly which elements might be related to the ones he’s molesting.
Mike: good point. Goes to show I have no practical experience with multiple people working on one CSS file (or at least, not at the same development cycle).
Dammit, Shaun… you just had to bring Mike into this, huh? Couldn’t handle it alone? ;-)
Kyle: Using a HERE doc is quite an elegant solution that I didn’t even consider (I should have since I was using one as my pseudo-buffer while developing the CSS-SSV function). The shortcoming there is (at least in BBEdit, my editor of choice) you lose all syntax coloring which slows down scanning the code—one of the original issues I was trying to overcome.
Faruk: I would also add (to Mike’s comment) that “tedious to type” wasn’t referring to length of variable names but having to type
<?php echo ...; ?>
or<?=...?>
every time you wanted to use one. The point isn’t shorter property values or variable names, it’s being able manage those values that are repeated from a single location/variable. That’s where the savings is.Shaun, you continue to amaze the hell out of me. Now I won’t have to type “Lucida Grande”, “Lucida Sans Unicode”, “Lucida”, “Bitstream Vera Sans”, “Verdana”, sans-serif; again for Business Logs! Hell ya!
Shaun: oh I agree, the PHP solution was dreadful at best. Nice idea, but I’d never use it, would drive me insane :)
I’ve played around before with PHP-generated stylesheets and they are really funky (a background image that moves every time you visit was one thing I played with at the start). The problem is the caching. You need to add something like this to the start:
waht about using global vars and declare these vars in a config_css.php.
Damn. For a second, there, I thought that Shaun had gone and implemented the calculations engine I mentioned back in Andy’s thread.
This is neat, though… I don’t have much use for it, but it does look as though it could have its utility. The first thing I thought of was all the colors I use in my designs… after a while, I can’t separate my #009933 from my #ADCDF6, and having constants like “lime” and “robinsegg” would save me all sorts of grief.
Of course, I could just mention demarkate those constants in a comment at the top of the sheet… but if my server can handle it, why not make my life that much more organic? I’m not a machine!
Re: Faruk’s comment on variable names — the easy way to get round that problem is to simply put a commented line with each variable name. That way you’re still saving on namespace, you’re getting variables, and there’s not much chance for misunderstanding on what a specific thing does.
Uh… and I second “constants” being better that “variables”, and not least because it creates a nice palindrome: CSS-SSC.
Heh.
I will admit that most of this discussion is over my head, but I love the idea of variables in stylesheets, because using find-and-replace risks replacing things you want to keep.
I’m sure those who have commented on this issue know more than I, but I’d call into question the assumption that a fully PHP-based stylesheet would be an excessive server processor hog. I’ve heard people complain about the extra work put on the server by leaving the trailing slash off a domain name (e.g. google.com instead of google.com/), which is absurd, and I wonder, similarly, how big a problem a PHP-based stylesheet would be for most servers.
How much of a performance hit are we really looking at? I assume this would be easy to test.
Nice stuff but too tedious for me. You need PHP + .htaccess to get it to work?
Just use whatever variables you want in your CSS and let PHP do the dirty work. Link to the PHP file as the stylesheet and preg_replace any variables you have defined in an associative array (or a separate file altogether).
It saves having to reply on .htaccess, and PHP can output proper headers for caching.
You could even cache the stylesheet so you can re-use it for a specific amount of time to reduce server load.
This is truly an ingenious trick, Shaun. My only experience is with small sites, but even there I bump up occasionally into the I-want-the-same-colour-in-six-places territory that surely plagues a lot of big projects.
And yeah, I didn’t like the idea of dumping PHP (or whatever) directly in there.
But this solution is really terrific. Quite marvelously spiffy.
To anyone questioning/complaining about server load: Just test the damn thing. This solution can be implemented and tested in a matter of minutes without you having to go through and make a ton of code changes. If you have a small to medium sized site hosted on decent hardware, I doubt you’d notice any performance problems. Is this a solution for sites getting millions of page views a day? Maybe not. But 99% of sites don’t fall into that category.
I have the same gripe as most of the people here. It’s firing up PHP every time the file is loaded.
Now, here’s a thought: Create a simple web-based file editor making changes to the stylesheet. When you save the file, it overwrites the old static file with a fresh one, with the variable figured out. Then save a separate copy with the variables not added, so you can edit again.
Of course, this is a bit restricting. Doesn’t let you use a nice text-editor with syntax-highlighting and all. One thing to make it easier would be the implementation of a line and text search like this one: theoneandtheonly.com/wordpress-editor-search
Not sure how convenient this would be, but it certainly solves the php-every-time problem. Perhaps this would be better as a plugin for a text-editor subEthaEdit. It would be a wicked cool feature for any text-editor, to have a global variable box that will be updated on-save. Meta-data about variables might be a problem though…oh well. Just thinking this through, it maybe a totally bad idea.
Speaking from experience here, the load of initializing PHP (especially when running as an apache2 module) is very low. The cost of performing a variable swap on a css file is very minimal compared to even the most basic of PHP functionality.
If PHP is a large concern, it is always possible to directly pass the CSS into the PHP on an interval (via cronjob) and generate a static file for the masses. If that’s something you need, look into ob_start() and ob_get_contents().
Even the most standard of servers handles these kinds of basic PHP functions with minimal impact. If you really need a static file solution though, scheduled processing can be a great asset.
Regarding caching, it would be pretty easy to just have your CSS-parsing script save a cache based on the timestamp of the original .css file. If the timestamp is the same, serve up the cache. Otherwise, re-process, save, serve.
I think it’s genius. This could open the door to having a master CSS document that defines your color palette, and then structural CSS documents for positioning, structural elements—everything else. That way when you decide to change the color scheme associated with a site it becomes as simple as redefining your CSS color palette.
I also have been looking for this sort of thing. We use JSPs so this trick doesn’t help me (I had my coders write me a taglibrary that pulls my values from a property file… same effect different approach).
At some point in the past, I recall having issues certain browsers not being happy when css or javascript files come back with extensions other than .ccs and .js. To get around this and still use JSPs, we wrote a servlet that might help out those of you who aren’t happy with the server load. I suspect that someone could write a combination of Appache Rewrite-engine voodoo and PHP to handle this.
Lets call our servlet Foo. All urls that look like /Foo/Some/Real/Path.css get run through this servlet. The servlet looks for /Some/Real/Path.css and forwards the request to that URL if it finds it. If not, it looks for /Some/Real/Path.jsp which it then runs and returns. Becuase server load is an issue for us, we cache the result. Our original solution was to simply save the rendered result at /Some/Real/Path.css so that subsequent requests would simply be forwarded.
The only real issue building a mechanism for eliminating the cached versions from time to time.
I know someone could implement easily enough.
Hi Shawn,
My service, Squarespace, has supported the notion of CSS variables for about a year now — which lets us make colors that are user-definable within stylesheets easy for users to select — but still flexible for designers. You can set “Style Variables” on a per-style basis, then reference them from CSS with $VarName$. The ending CSS result is cached on the Squarespace server for same-as-static loading.
In addition, with Squarespace 3.1, we’re releasing the ability to do simple math with CSS variables so that members can specify a “main column width” of XXpx, and a “sidebar width” of XXpx, and the subtraction/padding adjustments can occur properly and automatically within the CSS. 3.1 Should be out in something like a week. The net result allows things like:
#pageWrapper { width: $MainColumnWidth+SidebarWidth+40$ }
Etc. Maybe something to include in your version as well. The adding/subtracting function becomes REALLY useful.
If you’d like an account to play with the implementation let me know :)