CSS + PHP: Organized and Optimized?

Published in CSS on Tuesday, August 31st, 2004

Many of us break up our CSS based on functionality and create multiple style sheets. A little PHP can clean up the delivery of these stylesheets.

Updated on 01/09/2004.

While working the CSS for a design today, something occurred to me. Since we've been looking at using php with our css, many possibilities open up. These of course assume that you are passing your CSS to the PHP script handler...

Note that I am using PHP and Apache here.

Comments

I'd hinted at this before (and read about it on Webmasterworld, I believe). Put your comments in as PHP comments in your CSS. When parsed, the comments aren't delivered. Bandwidth saved, and you can comment to your hearts content.

Style sheet organization

Organized, not optimized

Many people, myself included, like to split up their CSS into multiple stylsheets based on function, and import these more complex sheets from a basic stylesheet. This keeps things happy and tidy for us coders, but isn't the most optimal in terms of downoading or effective use of requests and packets.

In addition to being poorly optimized, Opera users (is this exclusive to us?) will notice that the browser applies the CSS as it is downloaded, in plain view of day. So for sites that work with multiple sheets, each sheet gets applied as it is downloaded. Makes for some interesting browsing, but I for one don't really like it.

Put your parser to work

A simple answer that will optimize the use of multiple stylesheets is to use your PHP to stick the sheets together before downloading. In that way they go down as one sheet. Keep your sheets separate and manageable when it comes to developing, but all together as one piece for efficient downloading.

An example

Lets say that you have a basic stylesheet, then one for layout, one for your navigation, one for colors, and one for hacks. That's 5 stylesheets.

Get parsing

You need to first tell the server to parse your CSS document with PHP's script handler. This can be done by placing an .htaccess file in your CSS diretory with the following:

AddHandler application/x-httpd-php .css
php_value default_mimetype "text/css"

The first line tells it to send your CSS document to PHP, and the second line ensures that the correct mime type is sent for the parsed document.

Thanks to Matt for clearing up a potential problem here. If you don't have your CSS in it's own directory, skip the second line from above and add header('Content-type: text/css'); as the first line in the PHP provided below.

Stitch'em together

In order to join you stylesheets together, you could simply have a stylesheet called "stitched.css", for example, that would contain the following:

<?php
include("layout.css");
include("navigation.css");
include("colors.css");
include("hacks.css");
?>

The result from this is one css document named "stitched.css" that contains all of the contents of the indicated css files.

Import as necssary

The next step would be to include "stitched.css" somewhere so that the rules are applied. Many people use something like @import url(/c/somesheet.css); in their basic stylesheet to call other sheets. That will do here, but now you only have to import one sheet, your combined sheet.

Lets wrap it up..

I haven't heavily toyed with this yet, but it seems like a good idea. When doing this, I would keep in mind some of the things noted while exploring gzipping css, namely the caching issues; be sure and 'manually' deal with the caching.

We'll be testing this out and report back here...

Comments and Feedback

"In addition to being poorly optimized, Opera users (is this exclusive to us?) will notice that the browser applies the CSS as it is downloaded, in plain view of day."

It must be exclusive to Opera users, I haven't seen that!

Good ideas overall.

Hmph, another reason to go to mozilla, I'm guessin'. Funny, it loads one sheet, applies, then another, applies it etc. All in a matter of whatever it takes to load the page... Anyways, thanks Blake!

And why use php?

I mean, it's handy but also not as efficient as can be. Why not use different stylesheets when you're designing the page, then string everything together in a new stylesheet and throw all the comments away.

This way, comments and code are much easier to work with due to the manageable pieces (and in the future, there is always good reference material at-hand), and no extra parsing required with the site itself.

I feel that there's no need for letting the server do a little more work if it doesn't need to. It is incremental, but still... it adds up.

No need to get fancy. ;)

I like it, when you give it a crack let us know.

Haha, well, here's the kicker. I would set this up so that the "stitched.css" is cached, fully formed, and served unless deleted by me, the developer, at which time the script would automagically create a new one. So the server doesn't work too hard.

Why do this? In all honesty it is much simpler this way once it is set up and running, then having to 'hand-clean' a series of pages.

Also, having something like this built into our site CMS makes it a no-brainer...

Nice idea, and here is another aproach.

Nicely done!

php_value default_mimetype "text/css" would make text/css the default mimetype for every PHP parsed file in that directory. Probably what you want is something like header('Content-type: text/css'); at the top of the file.

Yeesh, thanks Matt. A holdover from the gzipping+css post and I didn't think that thru. In that post we applied the code I provided here within one's 'css' directory, so it wouldn't be any trouble. Your route is more portable, for sure... Off I go to edit...

Another way to gzip your css is to set with php.ini According to the php-manual the zlib.output_compression setting is prefered over the ob-gzhandler.

So another (better ?) option would be the following script:

ini_set('zlib.output_compression',TRUE); ini_set('zlib.output_compression_level',9); /* check settings: die(phpinfo()); */ header('Content-type: text/css'); header('Cache-Control: must-revalidate'); $ExpStr = 'Expires: ' .gmdate("D, d M Y H:i:s",time() + (60 * 60)) . ' GMT'; header($ExpStr);

You may have to check if the php was compiled with zlib-enabled, it's at the top of the phpinfo() output in the configure-command ('--with-zlib').

I have the need to use print, screen and all stylesheets. is there a workaround for that?

Proper xhtml please!

I merely scanned the article, so forgive me if I'm not making a useful comment here

You mention using PHP to load all of your useful CSS into one document. You can do this with CSS itself with the CSS import command. It works as follows:

@import url(actual.css);

You can put that into a css document called 'css.css', for example, and just call css.css to get the actual.css content

A simple answer that will optimize the use of multiple stylesheets is to use your PHP to stick the sheets together before downloading. In that way they go down as one sheet.

What I was trying to do here is avoid having multiple server requests for multiple files. By using the @import you get a request for every import. By suturing all of the sheets together on the server before sending them along there is only one request.

In a way this can be seen as nitpicky and not really worth it, but I find it much easier to have a sheet for my navigation (nav.css) and another for layout (layout.css), design etc. then to have one long sheet of styles.

So I use several sheets, but the server sticks them together (and caches the single sheet for me - that's another story) and delivers just one sheet.

Check out the blog categories for older content