CSS Variables Using PHP

Written by David Walsh on Monday, April 28, 2008


This article may feature code that is no longer best practice in MooTools.
Click here to learn what has changed to make your code framework-compatible.

CSS is an amazing formatting tool but it has one glaring omission: variables. In My CSS Wishlist, I proposed a PHP-like syntax for CSS variables. Using PHP, I’ve made the idea of easy, dynamic CSS a reality.

The Sample CSS

/* globals */
*		{ margin:0; padding:0; }
body	{ color:$body_text_color; font-size:$body_font_size; }

The above is a sample css file that we’ve named “default.css”. For those that don’t know PHP, any string that begins with $ is a variable.

The PHP

/* get the stylesheet */
$stylesheet = @is_file($_GET['stylesheet']) && strtolower(substr(strrchr($file_name,'.'),1)) == 'css' ? $_GET['stylesheet'] : 'default.css';
	
/* set the header information */
//will be output as css
header('Content-type: text/css');
//set an expiration date
$days_to_cache = 10;
header('Expires: '.gmdate('D, d M Y H:i:s',time() + (60 * 60 * 24 * $days_to_cache)).' GMT');

/* set the dynamic information */
//default css variable information
$default = array(
	'body_font_size' => '16px',
	'body_text_color' => '#00f'
);

//red css variable information
$red = array(
	'body_font_size' => '10px',
	'body_text_color' => '#f00'
);

/* extract the propery array's information */
extract($_GET['theme'] && ${$_GET['theme']} ? ${$_GET['theme']} : $default);

/* load in the stylesheet */
$content = preg_replace('/\$([\w]+)/e','$0',@file_get_contents($stylesheet));

/* spit it out */
echo $content;

There’s a fair amount going on in the PHP above:

  1. We check to see if a specific stylesheet is has been asked for. If not, we’ll use a default stylesheet template. In this case, the default template is “default.css”. We also check to make sure that the requested file is a “.css” file and that it file actually exists.
  2. We set the header information, including: the content type, which is “text/css”, and an expiration date, which isn’t required but recommended for caching purposes.
  3. We set keys and values of the variables we will use in our stylesheet theme. These key => values are stored in arrays so that we may have different themes. Above we have a “default” theme and a “red” theme. Note the differences in font size and text color.
  4. We check to see if a specific theme has been asked for. If not, we use the $default theme. If the requested them doesn’t exist, we serve the default theme.
  5. We read in the file content and replace any string beginning with “$” with the value specified in the PHP file’s theme.
  6. We echo the output. Done.

The Usage

<link rel="stylesheet" type="text/css" href="/stylesheet.php">

The Result

/* globals */
*		{ margin:0; padding:0; }
body		{ color:#00f; font-size:16px; }

Voila! Variables are replaced by their values in the output. That’s it!


Follow via RSS Epic Discussion

Commenter Avatar April 28 / #
SeanJA says:

How much slower would this be than say regular css?

Commenter Avatar April 28 / #

This is would be cool as a plugin into Mootools, jQuery. Then broad’n it to a plugin for theming.

Commenter Avatar April 28 / #
Scott Roach says:

It wouldn’t be technically slower at all because its all done on the backend. However it would take longer for the web server to serve the css as PHP has to assemble the css first.

Also it would be much safer to have the default and other themes be indexes of a multidimensional associative array. The line where you extract the variable could be a security whole. I could change $_GET['theme'] to something like ?theme=password. Then if you had an array with passwords in it called $password, someone could theoretically expose sensitive data. This way you are making sure the variable comes from the one array that you specify.

Ex:

$themes = array(‘default’ => array(‘default stuff’), ‘red’ => array(‘red stuff’));
extract($_GET['theme'] && array_key_exists($_GET['theme'], $themes) ? $themes[$_GET['theme']] : $themes['default']);

It would actually be safest to just all out get rid of the extract statement and use regex though.

David Walsh April 28 / #
david says:

@Sean: There’s no doubt that this type of PHP system would put more stress on a server than a simple CSS file, but caching the result periodically would help things out a lot. You could cache the result using PHP or server directives in an .htaccess file.

@Bob: Great idea! Something to think about for the future!

David Walsh April 28 / #
david says:

@Scott: Thank you for the suggestions!

Commenter Avatar April 28 / #

Hi!
In February I wrote a simple (really simple) tutorial on how to use php variables inside css files.
Why don’t just use inside the css file?
You can see the tutorial here.

Commenter Avatar April 28 / #

there is some missing information in the sentence:
“Why don’t just use inside the css file?”
I presume that information didn’t appear because it’s php code… What I was trying to say is: Why don’t just use php echo statements inside the css file?

Commenter Avatar April 29 / #

How often do your CSS files change? Do you really want to be serving them dynamically?

I understand completely the benefits that you get from using variables in your CSS files, but surely a better approach is to process the files once when you publish the site and create static CSS files from your input files.

That way, you get all the benefits of variables in the CCS without the performance hit of generating them dynamically for each page view.

Commenter Avatar April 29 / #
Bleyder says:

I think the best aproach in this field is to not use css constants vía PHP. Try reading the next article by Rachel Andrew:

http://24ways.org/2006/faster-development-with-css-constants

David Walsh April 29 / #
david says:

@Dave: Agreed. That’s why in my previous comment I mentioned caching. I would never roll out something like this on a customer’s site without caching of some kind. I’ve never actually used this, but just wanted to show it was possible. :)

Commenter Avatar April 29 / #
Jay says:

The so called stress is nominal and you could make it cache if you wanted to. I’ve thought about doing this in the past, I just haven’t. That’s usually bc when I’m creating a site in say drupal, I load different style sheets for different sections or content. And I put different ids and classes on content. So I just haven’t had a real need to do this I guess. I suppose there might be some sort of benefit, say perhaps you store some variables in a cookie where the user can customize the colors of certain sections. You have them change the colors in their settings and then you pull those settings in your css file.

Also browsers often cache css files as well.

Commenter Avatar April 30 / #

Hi, nice post. I use this technique too.
I posted in my blog something about using PHP to power up the CSS file.
It’s in portuguese.
http://www.codesignville.com
Thanks.

Commenter Avatar May 01 / #
Pedram says:

Dear Sir I did the Same in the Instruction but it didn’t work it only did the
*{…} which was statically it didn’t change Via the PHP …..
Can you test it again… my files name are index.php which has the LINK
stylesheet.php
default.css
all of them are in the same FOlder .. and THe LINk works but the Problem is in the PHP file thank
Pedram

David Walsh May 01 / #
david says:

@Pedram: WordPress stripped out some slashes I had in there — please try again.

Commenter Avatar May 01 / #
Pedram says:

Dear David I Emailed You on this EMail address …
david@davidwalsh.name

Commenter Avatar May 01 / #
Pedram says:

Dear David.
am I Using the correct right email address?

Commenter Avatar May 06 / #
Ben May says:

Great System! Very handy and useful, thanks heaps.. I will definitely be using this on a few projects I have.

Cheers

Commenter Avatar May 08 / #

Wouldn’t it just make more sense to append a different class to an element using PHP rather than rewriting the stylesheet each time? Using your example, I would write PHP to output instead of a regular tag. This keeps structure, logic, and presentation separated so front end designers don’t need to muck through PHP code to change the appearance of a site.

David Walsh May 08 / #
david says:

@Russell: I see your point. If you didn’t have PHP knowledge, this may not be a great system for you. That said, the PHP to do this is so easy that I assume a non-PHP person could easily learn the pattern.

Commenter Avatar May 22 / #
Jeremy says:

Would it be possible to add to your .htaccess file:
AddType application/x-httpd-php .css

Then your css file would be able to include configuration variables, which can be used by echoing them out in the css file the same way php is commonly used within html files. I haven’t tested this, but it “should” work.

David Walsh May 22 / #
david says:

@Jeremy: Yep, that would work. I’ve done it in the past.

Commenter Avatar May 24 / #
despistao says:

only work in internet explorer, in Modzilla does’nt work :(

The best chance is the one that has published @Tiago Cruz@. Easy, quickly and for all in the family hehe xD

thank you

Commenter Avatar September 01 / #

After a bit if experimentation, I found out you can use Apache’s SSI to do this. See http://ecoconsulting.co.uk/training/css_includes.shtml

Commenter Avatar October 22 / #
Matthew says:

Great System! Very handy and useful, thanks heaps

thank u r information

it very useful

Commenter Avatar October 26 / #
Vicente Benavent says:

Thanks a lot really usefull!!!

Commenter Avatar November 27 / #
Madhu says:

Hi,

Instead of using Dynamic css. We can maintain several css files which is very fast as compared to Dynamic css.

What about ur opinion regarding my statement.

Regards,
Madhu

Commenter Avatar November 27 / #

Madhu – each CSS file means another HTTP request, which takes time. I found the SSI method really quick, but it would be good to do some proper testing on the various alternatives (anyone?).

Commenter Avatar October 14 / #

How can we replace .php file over .css file

Very Simple.

STEP1: This is your abc.php page

<!—->

STEP2: This your zero.php (actually zero.css renamed with zero.php) page

#s1{
/*background:transparent url(../images/img_main.jpg) repeat scroll 0 0;*/
background:transparent url(../images/) repeat scroll 0 0;
border-bottom:1px solid #A0A0A0;
float:left;
height:208px;
position:relative;
width:1002px;
}

Commenter Avatar December 17 / #
Abeon says:

21 lines of code (minus your comments) is all it took for dynamic css :)

Great information, thanks!

Commenter Avatar December 18 / #

It no longer makes sense to struggle with this – Sass is there already. Write CSS with variables, functions, etc. (can also take existing CSS files and transform them), compile into static CSS files. Lovely.

Be Heard!

I want to hear what you have to say! Share your comments and questions below.

Name*:
Email*:
Website:  


© David Walsh 2007-2010. Contact David Walsh. Powered by the remarkable MooTools javascript framework.