Post #222

You are currently only viewing posts within the category: Site news
You are here: HomeArchiveSite news2004February3rd → this post

Dynamic @import CSS files using PHP

3rd February 2004, mid-afternoon | Comments (35)

Safari users, who until recently were greeted with a “Downloading 1 of 94 images” message when viewing this site, will be pleased to hear I’ve discovered the joys of combining PHP and @import CSS files — the result of which is that I’ve been able to shrink my weather-banner-CSS from ninety-five static rules (ninety-five!), to two dynamically generated ones.

Of course everyone else benefits as well, I’ve effectively reduced the amount of weather-banner-CSS you guys have to download from 16k to around 300bytes — that’s a 98% drop in file size.

Pretty nice, eh?

Sure you’ll lose the ability to cache that style sheet (what with it being dynamically generated), but it’s only 300bytes, hardly a big hit.

So, how did I do it? Well actually two readers helped put me on the right track: first of all David pointed me at some Evolt articles about using .htaccess to parse PHP files as CSS, and then Chris Neale stepped in and pointed out all I needed to do was stick header('Content-type: text/css'); into a PHP file to achieve the same thing.

How it all works

Each page on my site calls three style sheets, the second of which (scene-css.php) is actually a PHP file:

  1. <style type="text/css" media="screen">@import "/blog/include/layout.css";</style>
  2. <style type="text/css" media="screen">@import "/blog/include/scene-css.php";</style>
  3. <link rel="stylesheet" type="text/css" media="print" href="/blog/include/print.css" />
  4. Download this code: 222a.txt

This PHP file takes the values my weather script (scene.php) spits out and creates the relevant CSS rules. It also uses the header function to declare the output of the file as CSS:

  1. <?php
  2. // declare the output of the file as CSS
  3. header('Content-type: text/css');
  4.  
  5. // include the script that generates all the weather variables
  6. include('blog/include/scene.php');
  7. ?>
  8.  
  9. #header #scene p {
  10. background: url('/blog/commonpics/<?=$daynight?>/<?=$scene_class?>.jpg') no-repeat top right;
  11. }
  12.  
  13. #header {
  14. background: #fff url('/blog/commonpics/<?=$daynight?>/header-border.gif') repeat-x bottom left;
  15. }
  16. Download this code: 222b.txt

The output of which (as an example) is:

  1. #header #scene p {
  2. background: url('/blog/commonpics/day/clear-2.jpg') no-repeat top right;
  3. }
  4.  
  5. #header {
  6. background: #fff url('/blog/commonpics/day/header-border.gif') repeat-x bottom left;
  7. }
  8. Download this code: 222c.txt

And there you have it; two little rules. So much nicer than ninety-five. Thank you David and Chris.

Jump up to the start of the post


Comments (35)

Jump down to the comment form ↓

  1. Jon Hicks:

    Wow - I had no idea you could do this! It opens up so many possibilities.

    And just as Safari 1.2 solves the over-caching issue ! ;o)

    Posted 1 hour, 13 minutes after the fact
    Inspired: ↓ Joe Mcgill
  2. Ryan Parman:

    I'd been thinking about something like this for a while now, but I never really had a reason to try to implement something like this before.

    Good job!

    BTW, Feed Demon 1.1 Beta 1 now parses your [guid] RSS tags properly. Hooray!

    Posted 2 hours, 39 minutes after the fact
  3. Joe Mcgill:

    I have recently been thinking about creating dynamic style rules through PHP on a couple of projects that I have been working on lately. This is going to save me a lot of research time.

    I'm with Jon when he says the possibilities are endless. I think that this trick will soon be a standard of many web designers.

    Imagine:
    - using CSS in graphs where div widths or heights are dynamically updated by a database.

    - dynamically changing headers or ads using CSS (like you've done here).

    - having one sheet that sends the proper style rules to different sections of a site based on url and not needing to use extra markup in your page (ie body classes).

    Good find my man...good find.

    Posted 3 hours, 22 minutes after the fact
    Inspired by: ↑ Jon Hicks
  4. Sian:

    How do you find out about all this stuff?

    *boggle*

    Posted 6 hours after the fact
  5. Levin:

    The best thing with PHP generated styles is that it allows you to use variables:

    div{
    background-color: $BACKGROUND_COLOR;
    width: $PAGE_WIDTH - $SIDEBAR_WIDTH;
    }

    well, the possibilities are _endless_ ;)

    Posted 7 hours, 40 minutes after the fact
    Inspired: ↓ Jan Korbel
  6. Jan Korbel:

    Very good point there Levin... Just yesterday I ran through re-cycling little complicated CSS layout and said to myself: "Why there are no variables in CSS".

    Posted 17 hours, 40 minutes after the fact
    Inspired by: ↑ Levin
  7. Owen:

    I've been doing this for years (firstly with Perl, then with the PHP incarnation of the same script) primarily because the right mime-type is necessary. The main difference is that my application is useless, as the file only changes once every several months!

    Posted 17 hours, 48 minutes after the fact
  8. Jemal:

    Not to rain on your parade, but isn't that a lot of work compared to just using your css file to link to the php script that does the weather calculations and have that output the correct image? Something like:

    #header #scene p {
    background: url(/blog/scene.php) no-repeat top right;
    }

    And have scene.php return an image? I use Dan Benjamin's Image rotator (http://www.hiveware.com/imagerotator.php) in much the same way. (Except that it returns a random image.)

    Posted 20 hours, 30 minutes after the fact
    Inspired: ↓ Dunstan
  9. Dunstan:

    Someone else raised that issue, Jemal.

    The reason I don't do something like Hivelogic uses is that his images won't be cached, and mine are. If I don't use specific and unique image names then every time you visit the site you have to download a weather image afresh - something I, as a dialup user, wouldn't be too happy to do.

    Or if you mean why do I have PHP in the CSS file and not do it all in scene.php, well I don't think that's right either - scene.php is there to generate the weather variables, it's not there to output specific stuff for other pages.

    _Or_ if you mean why don't I just stick a PHP include in a regular CSS file? Well, that doesn't work, since the CSS file won't be parsed as PHP for the include to work.

    I hope that answers your question.

    Posted 20 hours, 46 minutes after the fact
    Inspired by: ↑ Jemal
  10. Kevin McDonagh:

    <Gasp>:0</Gasp>

    Posted 21 hours, 11 minutes after the fact
  11. Dave:

    www.cbso.co.uk does something similar to this subject so I thought I might post it;

    As I remember you set the variables you want in a php 'settings' file, which is included at the top of all the files you want to use it. You can then change the remembered style (cookie) using get strings. That scripts a little old, but I'm sure I could dig it out and update it a little if anyone would find it useful?

    Posted 21 hours, 59 minutes after the fact
  12. S T E F:

    erm...

    Not willing to point out that I *did* suggest it earlier on, but here's my 01/12 post to evolt's thelist telling you to do just that. Sheesh, why did I ever bother to write it? ;)

    http://lists.evolt.org/archive/Week-of-Mon-20040112/153758.html

    I'm just teasing you Dunstan actually, you did a great job, and my post was full of typos anyway, for instance:

    <cite>
    Then your CSS (embedded in a php file with the right mimetype)
    would read:
    #header {background: url(/blog/commonpics/night/clear-new-1.jpg) top
    right no-repeat;}
    or:
    #header .night-clear-new-2 {background:
    url(/blog/commonpics/night/clear-new-2.jpg) top right no-repeat;}
    </cite>

    should have read:

    <cite>
    Then your CSS (embedded in a php file with the right mimetype) would read:
    #header {background: url(/blog/commonpics/night/clear-new-1.jpg) top
    right no-repeat;}
    or:
    #header {background:
    url(/blog/commonpics/night/clear-new-2.jpg) top right no-repeat;}
    </cite>

    And voila...

    Posted 22 hours, 51 minutes after the fact
    Inspired: ↓ Dunstan
  13. Dunstan:

    I am _so_ bad at my Evolt email - I don't understand why some of it fails to enter my brain. Maybe because I get it in digest mode :o/

    In fact, I just checked, and I've never seen your message before Steph! I really must read my digest mails more carefully... damnit, I could have done this ages ago :op

    So, thank you for _trying_ to help me out, I apologise for my lack of attention :o)

    Posted 23 hours, 34 minutes after the fact
    Inspired by: ↑ S T E F
  14. Jason:

    I acutally had to use the header function in ColdFusion to send my style sheets as text/css as an interim solution. We had a problem with the web server sending the wrong MIME type with the CSS files. If you use XHTML doctypes with Mozilla and Mozilla is not given the correct MIME type for the CSS file it will refuse to load it. Once I figured out how to do this I tried all kinds of ideas with dynamic style sheets. Truth is I have never found a use I felt great about using.

    A point I would like to make. If you need to dynamically genertate CSS rules using PHP (or whatever language) you should always load the dynamic rules in a separate style sheet (just like Dunstan does). This way your static CSS rules will still be cached.

    Posted 23 hours, 41 minutes after the fact
  15. Sparticus:

    Not wanting to be stupid, but why couldn't you have just put something in like <?php include"path_to_file/$timeweathervariable.css"; ?> (I'm almost sure the code is wrong there, but you get the idea) and have different css files for different weather situations?

    Posted 1 day after the fact
    Inspired: ↓ Dunstan
  16. Dunstan:

    Because then I'd have 93 different CSS files with two rules in each one (the weather image and the night/day border). Not very manageable.

    Posted 1 day after the fact
    Inspired by: ↑ Sparticus
  17. Richard Allsebrook:

    The real benifit to generating dynamic CSS is you can use server side browser sniffing ($_SERVER["HTTP_USER_AGENT"]) to squirt clean CSS to standards compliant browsers and a seperate one to make it work in IE. It sure beats clogging up for CSS with nasty hacks!

    I'm in the process of writing an article for my blog on that very subject.

    Posted 1 day after the fact
    Inspired: ↓ Levin
  18. Yvonne Adams:

    Another wow! This came at the perfect time as I'm developing a site that needs extensive section-specific styles and I didn't want to have either a single 30-40K CSS file, or one basic file with a second 10K file for each section.

    Posted 1 day, 6 hours after the fact
  19. Levin:

    Richard,

    I don't really like that because then a page that is saved locally is not compatible in all Browsers. (Save a page in IE oben it again in Opera only to find out that it breaks horribly ... not good)

    This may also interfere with caching proxies

    Posted 1 day, 6 hours after the fact
    Inspired by: ↑ Richard Allsebrook
    Inspired: ↓ Richard Allsebrook
  20. Richard Allsebrook:

    Good point, well made Levin... but I suspect the vast majority of people who would save a local copy using one browser would use the same browser to view it again later.

    I supose a work around would be to put a note on the bottom of the page to the effect of 'This page is optimized for Internet Explorer - please visit http://www.domain.com/foo.php for other versions.'

    Posted 1 day, 18 hours after the fact
    Inspired by: ↑ Levin
  21. Pekka Heikkinen:

    Maybe this could be used, with the help of cookies, to remember style changes. When I switch to an alternate stylesheet, it resets back when I click a link. But if the alternate stylesheets would also set a cookie that would then tell the original stylesheet to import the alternate stylesheet instead of the original.

    Posted 1 day, 22 hours after the fact
    Inspired: ↓ Matthew
  22. Matthew:

    Paul Sowden has posted a way to do this over at A List Apart: http://www.alistapart.com/articles/alternate/

    I think that works better than what I think you're saying. If you don't mind using links on a page rather than a function built into Opera or Mozilla for example, I reckon Paul's idea is the best way to do it.

    Posted 2 days, 5 hours after the fact
    Inspired by: ↑ Pekka Heikkinen
  23. P01:

    Finally you did what I suggested you in your "Be nice to sheep" post ( http://www.1976design.com/blog/archive/2003/12/16/sheep/#cmnt500 ) ~__^

    Posted 2 days, 14 hours after the fact
    Inspired: ↓ Dunstan
  24. Dunstan:

    I don't know why people bother trying to help me out - this is something like the fourth instance of someone explaining this method to me ages ago, and me failing to take it in.

    Thanks for suggesting it so long ago then, sorry I didn't really listen :o)

    Posted 2 days, 21 hours after the fact
    Inspired by: ↑ P01
  25. Chris Neale:

    perhaps having a real name helps ?

    P01 suggested : http://www.1976design.com/blog/archive/2003/12/16/sheep/#cmnt487
    http://www.1976design.com/blog/archive/2003/12/16/sheep/#cmnt491

    whereas I was authoratitive : )

    http://www.1976design.com/blog/archive/2004/01/22/science-garden/#cmnt933

    Posted 3 days after the fact
  26. Markku:

    Well, I guess this proves only one thing -- PHP rocks! :)

    Posted 3 days, 1 hour after the fact
  27. Richard Allsebrook:

    As promised (threatened? lol) here's my article on Server Side CSS Sniffing: href='http://richardathome.no-ip.com/index.php?article_id=106

    Comments and suggestions always welcome.

    Posted 3 days, 18 hours after the fact
  28. Ronan Spoor:

    Dunstan, I emailed you and was thrown back an error. Seems your email account doesn't exist. My email is included so if you could get in contact :)

    Posted 3 days, 21 hours after the fact
  29. Bertrand Potier:

    If you're interested in this topic, I wrote an article some time agao related to what I've called "PHP Enabled Stylesheets" and which details how I implemented some skins behaviors for websites and applications. Find it at http://edreamers.net/?folder=articles&file=phpcss
    All your comments are greatly welcomed

    Posted 1 week, 1 day after the fact
  30. Martin:

    ok i have done this for a while...
    actually i have gone one step further (or in the middle of)
    im putting all the rules in a nicely ordered xml file then iterating over it in my dynamic file(asp.net... dont hit me i know but i think it rocks in some areas and in some areas i sucks) tehn making an online editor where you can alter the rules both visually and typing.
    also going to add some logic so that i will be able to lets say that you want a background picture display a random one from a list .

    Posted 5 months, 1 week after the fact
  31. Larry Larrigan:

    Would it be an idea to use this technique to work around browser incompatibilities?

    Use an if statement to determine the browser and output the relevant CSS. Would save tinkering about with various browser workarounds!

    Posted 10 months after the fact
  32. Vyper:

    Absolutely awesome bit of advice there, I've been trying for hours to get Mozilla to use a dynamic css file generated with php (worked fine in IE). All I had to do was add a header! I'm using it so that users for a site can use a completely customised colour scheme by reading their preferences from a database into the stylesheet.

    Cheers!

    Posted 1 year, 1 month after the fact
  33. Will:

    I had been looking for an example like this when I got my theory of "can i use php in a css file" bright idea thing. Turns out I was right, and this page has helped me demonstrate it.

    My blog is powered by pivot (www.pivotlog.net), and I had mentioned my theory over in their forums. I have posted the information from this post, as well as a link here. The post location is at http://forum.pivotlog.net/viewtopic.php?p=38935#38935. If you see referrers from here it's legit.

    This has helped out a bunch! Thank you!

    Posted 1 year, 1 month after the fact
  34. RossCo:

    Very impressive! Really impressed with the effectiveness and the implementation.

    Only downside is its a shame the javascript isn't x-browser for the scroll - as in IE 6 it causes a bit of havoc..

    Posted 1 year, 2 months after the fact
  35. Philip:

    Personally, I just stuff whatever PHP I need in the CSS file, like it's no problem. And I call it like this;

    <style>
    <? include ("stylesheet_name.css"); ?>
    </style>

    probably wrong, but it works well. PHP never gives you problems in inline CSS.

    Posted 1 year, 3 months after the fact

Jump up to the start of the post


Add your comment

I'm sorry, but comments can no longer be posted to this blog.