Creating a conditional CSS with PHP

9 Mar 2011 | Posted by: Paul Whittington
Creating a conditional CSS with PHP

We had a requirement to do this on a recent site as the design team wanted a lot of very subtle transparency. Ideally we wanted to use PNGs for a lot of this but, with IE6 support for transparent PNG being, well, non-existent we had an issue. We've used PNG-fix in the past but don't particularly like this solution. In this case we wanted to disable certain styles for IE 6 and change some background images on buttons from nicely anti-aliased PNGs to jaggy GIFs. We also added this module as it allows us to detect mobile devices in the style-sheet and apply different styles to the same HTML files.

Its pretty easy to run a conditional in the HTML and link to a completely different style-sheet for certain browsers. I personally don't like this solution as having the same styles in completely separate files is asking for trouble when sooner or later one CSS is updated and the other isn't and the site isn't checked in all browsers. This is especially likely to happen when multiple developers are working on the same files. Far better to have an if-then-else statement wrapped around the style inside the CSS, then its obvious what is happening.

Our requirement here is slightly different to a normal situation here as I could use our template engine to parse the file but the fundamental rules are the same and I've chnaged our code slightly to refect the more typical scenraio.

Part 1 redirect all of your filename.css requests to a server side script

I did this with an .htaccess script using:

RewriteRule ^([^.]+)$ /css_parser.php [NC,QSA,L]

 

Part 2 build a script that reads your css file and resolves the conditional statements

// set up an array to hold all of the values 
$visit = array ();
$visit["userAgent"] = $_SERVER['HTTP_USER_AGENT'];
$visit["remoteAddr"] = $_SERVER['REMOTE_ADDR'];
$visit["browser"] = "";
$visit["browserVersion"] = 0;

if (preg_match( '/mozilla.*applewebkit/([0-9a-z+-.]+).*mobile.*/si', $visit['userAgent'], $thisUserAgent ))	{ // Safari Mobile
    $visit['browser'] = "SafMob";
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif (preg_match( '/mozilla.*applewebkit/([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) { // Webkit (Safari, Shiira etc)
    $visit['browser'] = "Webkit";
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif ( preg_match( '/mozilla.*opera ([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent) || preg_match( '/^opera/([0-9a-z+-.]+).*/si', $visit['userAgent'], $aUserAgent)){ // Opera
    $visit['browser'] = "Opera";
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif ( preg_match( '/mozilla.*rv:([0-9a-z+-.]+).*gecko.*/si', $visit['userAgent'], $thisUserAgent )) {// Gecko (Firefox, Mozilla, Camino etc)
    $visit['browser'] = "Gecko";
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif ( preg_match( '/mozilla.*MSIE ([0-9a-z+-.]+).*Mac.*/si', $visit['userAgent'], $thisUserAgent )) { // IE Mac
    $visit['browser'] = "IEMac";
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif( preg_match( '/PPC.*IEMobile ([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) { // MS mobile
    $visit['browser'] = "IEMob";
    $visit['browserVersion'] = "1.0";
} elseif( preg_match( '/mozilla.*?MSIE ([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) { // MSIE
    $visit['browser'] = "IE";
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif( preg_match( '/mozilla.*konqueror/([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) { // Konqueror
    $visit['browser'] = "Konq";
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif( preg_match( '/mozilla.*PSP.*; ([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) {// PSP
    $visit['browser'] = "PSP";
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif( preg_match( '/mozilla.*NetFront/([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) {// NetFront
    $visit['browser'] = "NetF";
    $visit['browserVersion'] = $thisUserAgent[1];
}

 

Step 3: markup your css file

Although this is stored as a CSS file we can write normal PHP code into here and then parse it later with an 'eval'. 

/*stylesheet*/
body {font-family:arial, helvetica, sans-serif}
/*now we are going to wrap a conditional around our link class*/

    
        a.button {position relative; display:block; width 24px; height: 24px; background-image:url(../images/IE6_button.gif)
    
        a.button {position relative; display:block; width 24px; height: 24px; background-image:url(../images/button.png)
    

    a.button {position relative; display:block; width 24px; height: 24px; background-image:url(../images/button.png)

Part 4: finally we need to evaluate the CSS and return it the visitors browser

$pathToFile = "" // here you will somehow have to get the path to your css file, it might be that you only have one so you can add a static value, it might be that you need to get which file was called by using $_SERVER['REQUEST_URI'] or something..
eval("$cssContents = "".file_get_contents($pathToFile)."";");

You now have the parsed css contents in a variable ($cssContents) and you need to send this file back to the users browser.

$expires = 60*60*24;<
header('Pragma: public');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMTn');
header('Content-Disposition: inline');
header('Cache-Control: maxage='.$expires');
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT');
header('Content-type: text/css');

print $cssContents;
exit;

 

That should be it, as usual any feedback or addtions would be appreciated, if you have a similar article post a link and if we think its relevant will post it here.


 

Please rate this article

Click the stars below to give this article a mark out of 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 5 / 10


Related Articles

How to use z-indexing in CSS
7 Apr 2010 | Posted by: Keir Cleland
Learn how to enhance your web pages using the z-index property
82% rating, 1 comments

PHP upload progress bar
7 Apr 2010 | Posted by: Paul Whittington
Creating a php upload progress bar in PHP is notoriously difficult...
82% rating, 1 comments



Post your comments...

We would really appreciate any comments or additions that you have. Include a link in your comment and if we think your comment is appropriate we will publish it. If found this article in any way useful we would really appreciate you bookmarking the page with any of the social bookmarking links provided.

Nice feature, I have a leader ecommerce site in Spain and I would like to get more information about your CMS. Could you please send me an email with further details? Many thanks
Posted By: Juan - 14 Mar 2011


Name:
(optional, shown on site)
Email:
(optional, never shown on site)
Code:
(case sensitive)
captcha
Your feedback: