Compress CSS on the fly

Oct 1st, 2007 by Jared Schwager , ,

In an attempt to further speed up loading times for Grupenet, I decided to compress (remove spaces and comments) my CSS stylesheet. However, instead of applying compression directly to the original file, why not add some PHP code to the stylesheet to compress the CSS dynamically when it is loaded on the server? This way all readability is maintained when editing the original file. This way you can add as much commenting as you need to keep your CSS more organized.

Step 1

Create a new file called .htaccess in the same directory your stylesheet is in. Open your newly created .htaccess file and add the following lines:

<Files style.css>
SetHandler application/x-httpd-php
</Files>

(Replace style.css with the filename of your stylesheet)

Step 2

Open up your stylesheet and add the following to the top of your stylesheet:

<?php
header('Content-type: text/css');
function compress($buffer) {
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
$buffer = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $buffer);
return $buffer;
}
ob_start("compress");
?>

Now add this to the bottom of your stylesheet:

<?php ob_end_flush(); ?>

Step 3

That’s all there is to it! Now open up your browser and point it to your stylesheet. All the comments and spacing should be removed, and it should look something like this.

14 reader comments

  1. October 11th, 2007 at 10:21 am Chris Coyier says:
    Chris Coyier's Gravatar

    Very nice. Seems to be very effective in your example. I wonder how that would effect server load on very large websites, since instead of just serving up the CSS it has to do a little processing first.

  2. October 15th, 2007 at 12:51 pm Links of Interest - CSS-Tricks says:
    Links of Interest – CSS-Tricks's Gravatar

    [...] Schwager has an interesting idea on compressing CSS on-the-fly using PHP. Works pretty well. The end result is slightly quicker downloads and slightly quicker [...]

  3. October 16th, 2007 at 6:25 pm Jared Schwager says:
    Jared Schwager's Gravatar

    Chris, I was also thinking about that as I implemented this on my site. I’m going to dig around the web to see how hard it might be to implement a cache system so the stylesheet wouldn’t need to be processed every time it is loading.

  4. October 21st, 2007 at 4:30 pm Rithiur says:
    Rithiur's Gravatar

    Well done. You’ve just successfully negated one of the primary reasons for using stylesheets: browser cache.

    You see, one big advantage with CSS stylesheet files is that browser can cache them for a time, so that they do not need to be loaded on every page load. This gives nice performance boost, and saves plenty of bandwidth with bigger stylesheets. However, dynamic pages which are created with PHP can not be cached because the server can not determine the modification date for the file.

    So, your compression script is actually causing significant increase in load due to increased bandwidth and processing required for the PHP file.

    If you want to use something like this, you should rather use a separate script to “build” the CSS file from original copy and store that, rather than create a dynamic file. But without this kind of “caching”, the script completely backfires.

    Also, three things about your code:

    1. The regex is interesting. Sure, it works, but it would be considerably easier just to use ungreedy matching like “!/\*.*\*/!Us”
    2. The str_replace doesn’t display properly in the blog post. If you just copypaste from there, you end up removing all the whitespace in the CSS, which is not very good idea.
    3. The compression logic is flawed. You can’t just go around removing whitespace like that. Newlines are just as valid whitespace as space character. If you for example separate values of border-width with newlines, that “compressor” will end up removing the separating whitspace. Mostly safe method to remove whitespace would be replacing “/\s+/” with ” ” (single space), because multiple whitespace is rarely needed (only actually matters inside quoted values, which shouldn’t be a problem).

    But, as I said, one of the major advantages of CSS files is local caching, and thus compressing your CSS files is mostly just wasted effort.

  5. October 22nd, 2007 at 12:23 pm Jared Schwager says:
    Jared Schwager's Gravatar

    Rithiur, I can’t believe I hadn’t thought of that before. Great point! I’ve definitely learned a couple new things today. I’m somewhat new to PHP, so thanks for the pointers!

  6. November 20th, 2007 at 5:07 pm Karol Krizka says:
    Karol Krizka's Gravatar

    Hmm, your example does not seem to work here. But nevertheless, it is a very good idea. Also implementing the changes that Rithiur recommended would be a good addition. Finally you should be able to compress your HTML code in a similar way, no? What do you think?

  7. November 21st, 2007 at 10:05 am Jared Schwager says:
    Jared Schwager's Gravatar

    Karol Krizka, I actually removed the code from my website after reading the points that Rithiur made.

    I may try my hand at making a script that will compress HTML also, but I’m still learning about how to use regex in PHP. It can get quite confusing at times.

  8. January 24th, 2008 at 12:54 am passerby says:
    passerby's Gravatar

    This is a great suggestion and works awesome. If you implement the PHP header expires function you can cache the css file for as long as you like.

    $offset = 60 * 60 * 24 * 1;
    header(“Expires: ” . gmdate(“D, d M Y H:i:s”, time() + $offset) . ” GMT”);

    That would make the css file cached for about 2 days. You can adjust that as needed. Have a good day. :)

  9. August 1st, 2008 at 1:40 pm Comprimiendo con PHP el código de tu hoja estilos CSS dinámicamente - elWebmaster.com says:
    Comprimiendo con PHP el código de tu hoja estilos CSS dinámicamente – elWebmaster.com's Gravatar

    [...] Fuente: GrupeNet [...]

  10. October 30th, 2008 at 7:22 pm Mario says:
    Mario's Gravatar

    In my experience compressing the css does make it a little lighter, but if done dynamically it actually takes a little more time to get to the browser client because of the overhead removing the whitespace.

    To make it cacheable you can configure your apache to add an expires header or do it by sending the header using PHP as passerby said.

    I decided not to use ob_start method because it actually made it slower for the browser to get it (~110ms compressing vs. ~75ms natural) what i did do was to generate one whole big CSS file from several files to reduce the number of requests made to the server.

    If you still want to compress your CSS dynamically I found a better function at http://php.oregonstate.edu/manual/en/function.php-strip-whitespace.php (look in the comments).

  11. March 31st, 2009 at 4:31 pm KTB says:
    KTB's Gravatar

    Heres a even simpler method to save a huge amount of bandwith:

    # A Week Expires header from askapache

    Header set Cache-Control “max-age=604800, public”

    # compress all files from :http://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/

    SetOutputFilter DEFLATE

    #Etags From: http://httpd.apache.org/docs/2.2/mod/core.html#fileetag
    FileETag MTime Size

    I love this one^^

  12. October 28th, 2009 at 4:37 pm Mike says:
    Mike's Gravatar

    I recently built a mod_perl output filter which runs inside Apache. It intercepts requests for .css files and compresses them on the fly. It doesn’t mess with any cache headers. See here:

    Compressing CSS on the Fly

  13. February 16th, 2010 at 10:59 am mario says:
    mario's Gravatar

    code thanks admin..

  14. February 21st, 2011 at 11:11 am Tony says:
    Tony's Gravatar

    I had a problem using firebug with files compressed this way.

Leave a comment

Allowed XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>