Posts from Thursday, January 22nd, 2009

Using HTTP Headers to Serve Styles

Published 9 years, 9 months ago

How many times have you played out the following scenario?

  1. Makes local changes to your style sheet(s).
  2. Upload the changes to the staging server.
  3. Switch to your browser and hit “reload”.
  4. Nothing happens.
  5. Force-reload. Nothing happens.
  6. Go back to make sure the upload is finished and successful.
  7. Reload again.  Still nothing.
  8. Try sprinkling in !important.  Upload, reload, nothing.
  9. Start swearing at your computer.
  10. Check Firebug to see what’s overriding your new styles.  Discover they aren’t being applied at all.
  11. Continue in that vein for several minutes before realizing you were hitting reload while looking at the live production server, not the staging server.
  12. Go to the staging server and see all your changes.
  13. Start swearing at your own idiocy.

This happened to me all the time as we neared completion of the redesign of An Event Apart.  It got to the point that I would deliberately add obvious, easily-fixable-later errors to the staging server’s styles, like a light red page background.

Now that we’re launched and I have time to actually, you know, think about how I do this stuff, it occurred to me that what I should have done is create a distinct “staging” style sheet with the obvious error or other visual cue.  Maybe repeat the word “staging” along the right side of the page with a background image, like a watermark:

html {background: url(staging-bg.png) 100% 50% repeat-y;}

Okay, cool.  Then I just need to have that served up with every page on the staging server, without it showing up on the production server.

One way to do that is just make sure the image file never migrates to production.  That way, even if I accidentally let the above CSS get onto production, the user will never see it.  But that’s inelegant and wasteful, and fragile to boot: if the styles accidentally migrate, who’s to say the image won’t as well?  And while I’m sure there are all kinds of CMS and CVS and Git and what-have-you tricks to make sure that doesn’t happen, I am both clumsy and lazy.  Not only do I have great faith in my ability to screw up my use of such mechanisms, I don’t really want to be bothered to learn them in the first place.

So: why not send the link to the style sheet using HTTP headers?  Yeah, that’s the ticket!  I can just add a line to my .htaccess file on the staging server and be done.  Under Apache, which is what I use:

Header add Link "</staging.css>;rel=stylesheet;type=text/css;media=all"

Those angle brackets are, so far as I can tell, absolutely mandatory, so bear that in mind.  And of course the path in those brackets can be absolute, unlike what I’ve shown here.  I’m sure there are simple PHP equivalents, which I’ll leave to others to work out.  I really didn’t need to add the media=all part, but what the heck.

Seems so simple, doesn’t it?  Almost… too simple.  Like there has to be a catch somewhere.  Well, there is.  The catch is that this is not supported by all user agents.  Internet Explorer, for one; Safari, for another.  It does work in Opera and Gecko browsers.  So you can’t deploy this on your production server, unless of course you want to use it as a way to hide CSS from both IE and Safari.  (For whatever reason.)  It works great in Gecko-based production environments like mine, though.

I looked around for a quick how-to on do this, and couldn’t find one.  Instead, I found Anne van Kesteren’s test page, whose headers I sniffed in order to work out the proper value syntax; and a brief page on the Link header that didn’t mention CSS at all.  Nothing seemed to put the two of them together.  Nothing until now, that is.