Treehouse

CSS Variables Using PHP

By on  

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!

ydkjs-1.png

Recent Features

  • CSS&nbsp;Gradients

    With CSS border-radius, I showed you how CSS can bridge the gap between design and development by adding rounded corners to elements.  CSS gradients are another step in that direction.  Now that CSS gradients are supported in Internet Explorer 8+, Firefox, Safari, and Chrome,...

  • Animated 3D Flipping Menu with&nbsp;CSS

    CSS animations aren't just for basic fades or sliding elements anymore -- CSS animations are capable of much more.  I've showed you how you can create an exploding logo (applied with JavaScript, but all animation is CSS), an animated Photo Stack, a sweet...

Incredible Demos

Discussion

  1. How much slower would this be than say regular css?

    • Very much slower, but it is fun to know. Although not many people will use this insted of normal css :-p

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

  3. Scott Roach

    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.

    • Brandon

      not so much, as the $_GET['theme'] he’s calling on is only for stylesheet.php, which is linked to his html document. they could certainly hack in and steal his other styles. that would, however, be no real tragedy.

  4. @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!

  5. @Scott: Thank you for the suggestions!

  6. 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.

  7. 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?

  8. 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.

  9. 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

  10. @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. :)

  11. Jay

    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.

  12. 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.

  13. Pedram

    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

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

  15. Pedram

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

  16. Pedram

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

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

    Cheers

  18. 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.

  19. @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.

  20. 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.

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

  22. despistao

    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

  23. 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

  24. Great System! Very handy and useful, thanks heaps

    thank u r information

    it very useful

  25. Vicente Benavent

    Thanks a lot really usefull!!!

  26. Madhu

    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

  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?).

  28. 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;
    }

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

    Great information, thanks!

  30. 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.

  31. This seems like quite a complex solution for something simple that you were originally looking to achieve; variables in CSS.

    Surely it would be easier to simply link to a master.php from your document, add in the ‘header text/css’ and then define some variables at the top of your document?

    Alternatively of course there are now utilities such as SASS that make this idea a little redundant.

  32. Cool, thanks a million. I will give this a try :-)

  33. Great system, very usefull and handy!

  34. Hey David,
    First comment on your blog. I read your posts from time to time though. You do great stuff.
    Two questions though:
    Would you personally use this over something like less.css.js? Or the LESS compiler?

    Also, I tried something similar to this technique before on my WordPress insallation. Since wp recognizes a theme in the style.css file i think my header at the top confused it becuase my theme was still active but my template selector under pages stopped working.

    In other words when I made a page I couldnt select a template file to use.

    When I went into the themes panel it said my theme was not active but when I visit the front end it was still showing. When I removed the php from styles.css it began working again.

    Do you know a WordPress friendly way of using this technique?

  35. It is complex, but usefull to know :) Thanks for sharing, although I think I’ll stick to another way.

  36. thanks, this post is really great, i appreciate your thought, i am sorry for my bad english :(

  37. I prefer this solution over the css preprocessors. I had too much difficulty with reliability using SimpLESS, and the mixins were also unreliable. At least with this approach, I know that where I place a variable in my CSS, I will get a direct replacement of that text with the string in my array.

    @Russel Bishop, no, because putting CSS into PHP is unworkable. It’s not clean and the code highlighting is off.

    @David Walsh, I’m getting an error on this line:

    extract($_GET['theme'] && ${$_GET['theme']} ? ${$_GET['theme']} : $default);

    The error is “Undefined index: theme”.

    I’m not sure what $_GET['theme'] && ${$_GET['theme']} is intended to do, but I think what you want is this (and this is what fixed the issue):


    extract( isset($_GET['theme']) ? ${$_GET['theme']} : $default);

  38. Wow this looks complicated. But somehow usefull I guess :p

  39. Tony Di

    I am new to PHP and would like to apply CSS typographic and page layout elements to the dynamic data presented for my long description of a product page. My product database is in place and I can pull the product data and images to my page with no problem, but I would like to format the long description text and present the data using CSS or HTML.

    I have a list in the middle of 4 paragraphs that is now presented as one big paragraph.

    Anyone’s help would greatly be appreciated.

    Tony Di
    tony@awarzone.net

  40. Too complex for me to understand now… I am busy with learning both skills, so this could be interesting very soon!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!