Check Firebug to see what’s overriding your new styles. Discover they aren’t being applied at all.

Continue in that vein for several minutes before realizing you were hitting reload while looking at the live production server, not the staging server.

Go to the staging server and see all your changes.

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:

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.

Followup: Also note that if you’re in an environment where your IP is static and you’re only editing CSS and you don’t mind testing those CSS changes on your live productoin server, then there’s a way to use redirects based on IP to get a somewhat similar effect. Not exactly the same, I grant you, but similar.

Hi Eric. This is a great post. I would’ve never thought to serve style sheets in such a manner but I can totally see where it would come in use. I’m going to keep this in my arsenal for later use.

Also, I’ve done loads of bone head things like that as well. We all have our moments. The other day I was editing a template for a module on a CMS and wondering why the changes weren’t being applied. Turned out I was editing the entirely wrong template. This went on for about 10 minutes before I realized it.

We use a Greasemonkey script that knows what environment we’re looking at (development, staging, production) and injects an appropriately-colored and labeled div up at the top of the page to let us know what we’re looking at. Tremendously useful. (Of course this is pretty much a Firefox-only solution, though we’ve also cooked up an IE-compatible equivalent as well.)

Foolproof… until the .htaccess file accidentally migrates itself to the production server. :-)

However, for small one- or two-person projects, an alternative would be the Stylish extension, which allows Firefox to implement custom styles on any domain (or subdomain). This way, any staging code is confined locally to the developer’s browser and does not appear on the staging server at all. Use in tandem with Server Switcher and you’re good to go.

Foolproof… until the .htaccess file accidentally migrates itself to the production server.

Yeah, there’s that. My deep and abiding fear of .htaccess files makes it much less likely that I’ll migrate it by mistake, but it’s still a risk.

I really like the Stylish/Greasemonkey ideas, at least for solo projects. When working with geographically distributed teams, it only works if everyone’s a developer, which is almost never the case for me.

Great tip! It might be worth noting that if you do by chance actually specify an html background image in your real style sheet, it will override the CSS in the staging one. Perhaps obvious…but when we’re talking about stupid mistakes, you never know!

Now can you come up with a way to add the closing brace I accidentally deleted while I wonder why only half my style sheet is being applied, or a way to automatically fix my CSS when I’m refering to the wrong selector all together?!

As you say “I”m sure there are simple PHP equivalents”. PHP not being my strong-point, I recently did something more with PHP than I had before and used:

$theUrlIwantToTest = $_SERVER['HTTP_REFERER'];
andpreg_match

to test for the URL that I had been referred from. Guessing PHP would also allow one to test the URL a page was displaying on and if it partially met that of the test server then one could serve the extra style sheet.

I’m not PHP-y-enough to say what that code would be, but guessing it would be small and I _think_ it would make it more cross-broswer than the .htaccess solution perhaps?

Using Safari Stand though, I used Site Alteration to deliver one custom stylesheet when viewing prod and another for dev. It’s been fantastic. Now, it naturally only works on the machine for which I have it installed, but that’s where I do all the work anyway.

I know there’s extensions out there to do the same thing for Firefox. I just haven’t bothered, since I always open what I’m working on Firefox from Safari (using Developer > Open Page WIth menu).

Rarely am I surprised by any new techniques anymore but this impressed me. Well done!

To those adverse to .htaccess files and who may have a little more control over their servers, I highly recommend popping the details into the httpd.conf. Highly unlikely it’ll get moved over in migration. Avoid .htaccess altogether, and turn off .htaccess in the httpd.conf, and you should see a performance boost as Apache no longer has to search up the tree to find an .htaccess file.

1) If you wanted to be absolutely sure you”ll never accidentally serve up a “STAGING” CSS file, instead if having the Link header point directly to the CSS file, it could point to the PHP file I included below.

2) To ensure the .htaccess files”s accidental copying to a live server would not start sending needless files to live site visitors, the PHP file below could be trivially changed so as to write <link> tags instead of sending headers and included in your website / theme files.

3) Serving a JavaScript file instead of the CSS file could work as well, and could even test for the hostname before applying itself. (Of course, you wouldn”t want to serve that file to the live site anyway, as it would be a pointless performance and load-time hit.)

As you noted, support for Link is spotty; that appears to be why it was dropped from RFC 2616. Felt it worth pointing out, though, that while it does work for stylesheets in Firefox, it’s not consistently supported for other values.

You’re kind of missing the whole point, Mark. You might want to read the article again.

That works well for PHP environments, Zachary, but not every page is based on PHP. My original goal was to have something that would work no matter what kind of page was being served up. Perhaps I wasn’t clear on that point.

The HTTP Link header has been tested in Ian Hickson’s import tests for ages; those tests probably date back to around 1999 or 2000. (I think it might only be tested in part 2; I didn’t find any tests in part 1 with a quick scan.)

Great solution to a common problem. Now, have you figured out how to solve the issue of typos in the selectors and typos in the path to the stylesheet? Gets me every time. At least I’m blond, so I have an excuse.

Great technique! Pity it’s not supported by more browsers. Given that this only works in Firefox and Opera, you could also do this by running user stylesheets. It does mean everyone has to set it up, but you never have to worry about accidentally publishing it.

in that last one, check the space after url. In FF this works, in IE it breaks.

Well actually that background url problem I usually spot right away because I know it so well. The accidental quote was a really hard one recently, because I use an elegant font in my stylesheet editor (topstyle). The quote (`) was hardly visible.

In the past I’ve played with this “problem” too … ended up coding a firefox extension that colors the location bar based on which URL you’re at.

Only problems with my approach (and things I had coded quickly):
– it only worked on Firefox 2, Windows. Then Firefox 3 came out and I dropped the project
– no support for other browsers (IE, Safari, Opera, …)

Never thought about doing it like that – pretty interesting. I’ve never liked .htaccess though – not all servers have it enabled. You can use a service like http header viewer to make sure that your trick is working

Foolproof… until the .htaccess file accidentally migrates itself to the production server. :-)

True, true. And to prevent that — provided I have the privileges — I would put the ‘Header’ line in a <Directory> section of my apache configuration file (httpd.conf).
<Directory /path/to/webroot>
Header add Link "</staging.css>;rel=stylesheet;type=text/css;media=all"
</Directory>

Now that the directive is safely stashed away from my development webroot, I’ve further reduced the possibility of accidental migration. Or at least I’ve passed the responsibility for it to my server admin ;)

By the way, how standard is it for Apache admins to enable mod_headers? I know my host has it, but I don’t know if it’s common practice.

This approach is really interesting. I propose a slight variant below which should support any browser. It continues to depend on Apache, but moves away from using HTTP headers to just serving the modified css using rewrite rules.

1) Staging CSS:

@import “public.css”

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

2) Production.css:
@import “public.css”

3) Public.css: Style rules for the production environment

3) Use an Apache rewrite rule on staging servers to rewrite requests for production.css to requests for staging.css

This does cost an extra hop even in production, so it may not be optimal for production sites. One way to address this would be to setup a rewrite rule in production that rewrites requests for production.css to public.css. This saves the hop, but nothing breaks if the rule is omitted.