This post is the source for the most definitive/recent/tested method (in the scope of this blog) of gzipping your CSS when either Apache compression module is not available for use. Note: This post was originally published on June 13th, 2004. It is being republished today because: the topic has been discussed in a few places recently, and, well, I accidentally republished it when editing it.

Background Info

This whole idea started back in February of 2004 and has evolved through several iterations thanks to feedback from different users.
Because of these iterations, pieces of this concept are strewn about several posts on this blog (see history, below). This post is being written with the objective of holding the most recent and up-to-date version for gzipping your CSS. My apologies for the poor management of this topic. Lesson learned.

Why and how?
CSS files for larger sites can become pretty large themselves. Gzipping or compressing these files has shown to provide a reduction in the neighborhood of 70-80% of the original file size, a fairly significant 'weight loss'.

The obvious method to accomplish compression (on an Apache server) is to use either the mod_gzip or mod_deflate module (more here), these modules are not available to everyone. If you have access to those modules, follow the given link, otherwise... PHP provides an alternative compression method (two actually) and this is exactly what we'll leverage here - so one could think of this method as a 'poor man's mod_gzip'.

Outline
There are two different, equally effective methods that can be used.

The first method involves adding a little snippet of PHP to the top of your CSS file, and then renaming your CSS file with a 'php' extension. The second, cleaner and more elegant solution involves adding two little files to your CSS directory, one of them an .htaccess file, the other a PHP file that contains the same snippet of code used in the first method.

The snippet
A little bit of PHP magic is needed to make this happen. The following code is all it takes:
<?php
ob_start ("ob_gzhandler");
header("Content-type: text/css; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 ;
$ExpStr = "Expires: " .
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
?>
This code does 4 things:
It uses PHP's ob_gzhandler to send compressed data. This function will first check to see if the browser requesting the file will accept 'gzip,deflate' encoding; if not it sends the file uncompressed.

It sends a header for the content type and character set for the file - in this case text/css and UTF-8.
The next step sends a 'cache-control http header'. Here 'must-revalidate' ensures that any information that you pass along about the freshness of your document is obeyed.
The final step is to send an 'Expires' header, to set an age on how long our cached file will last. Here we set it to expire in one hour.
Method One
This method, though not as clean as the second, is just as effective. All you need to do is place the PHP snippet from above into the top of your CSS document. Then, rename your CSS file with a 'php' extension, and then refer to that file when linking your css file, for example:
@import url(mycss.php);
Method Two
Method two is cleaner and more elegant, as it does not require the addition of any extra code to your CSS file, nor do you have to change the extension of the file. Clean and simple.
Two steps are necessary to implement this method.
Step one
First, you want to save the snippet provided above in a file called 'gzip-css.php' to the directory that contains your CSS files.
Step two
Here, simply add the following to an .htaccess file and save the file to the same directory as your CSS files:
AddHandler application/x-httpd-php .css
php_value auto_prepend_file gzip-css.php
php_flag zlib.output_compression On
This code does 3 things:
The first line tells Apache to send all .css files to the PHP script handler.
The second line prepends the code snippet to your CSS file.
Optional: The third line tells PHP to use its built-in negotiated output compression automatically for every page it parses. If you use this method for compression, there is no need for having ob_start ("ob_gzhandler"); in the code snippet. So choose one or method or the other (see note).


Thanks to David for noting that this will prepend the file to all files found in the directory being used, so best to keep only CSS files in this directory.


Some notes
Confirmation
It is recommended that you check to see that this method is in fact working for you. Some people have reported that method one works fine while method two doesn't.
As with anything, do your homework! Test locally first, on a testing server, and be sure to examine the log files of your server to ensure that this is working!
Compression
PHP offers two types of compression, you can make an informed decision on which one to use by reading up on them: ob_gzhandler, zlib compression.
Caching
While the CSS files are explicitly set to cache, in our tests, Opera doesn't seem to cache the files when compressed.
Parsing
Some people expressed concern about invoking PHP's parser for this, wondering if it would either tax the server or result in no overall speed benefit.
With respect to the first concern, as the CSS files are cached, the file need only be processed on the first visit. As such, we have not observed this to be much of a concern.
With respect to the second point, we've seen 70-80% reduction in the delivered file size. So for a 10K CSS file, your looking at a reduction of 7.5kb, for example. Though this may seem like much, it is significant - would you be willing to add another 7.5kb to your header graphic for no reason at all? Neither would we!

History
For reference, here is a list of past posts related to this topic:

Discussing CSS Management and Optimization
Applied CSS Management and Optimization
Http Compression - Results and user numbers
Organizing and Optimizing Your CSS - Some ideas
More Notes on Gzipping CSS
Gzipping your CSS with PHP

Thanks
A thank you should be extended to all those who gave feedback and helped to extend and get this to the point that it is, in particlular Alun Bestor and Robbert Broersma.
Thanks to Lars Kasper for catching the missing charset in the Content-type header.
Feedback
If you have an idea, comment or suggestion pertinent to this topic, please let us know via our contact form.


Discuss  |   Share  |  Sink
Comments Who Floated Related Links
TopOfBlogs