Vars in CSS

How to Add Variables to Your CSS Files

Mar 18th, 2009 in HTML & CSS by Jay Salvat

Let's try something different on nettuts+ today. Any designer who has worked with large CSS files will agree that its major weakness is its inability to use variables. In this article, we will learn how to implement variables by using PHP and Apache's URL rewrite mod.

PG

Author: Jay Salvat

Hi, I'm Jay. I'm 35 and live on the French Riviera. Involved in the world of the Internet since 1997, I'm now leading the web developement team at Kuantic. I'm also trying to make the web a little better with some open source projects known as markItUp! and SundayMorning or with this modest french blog.

Preface

This technique is somewhat simple. We will ask Apache to redirect any stylesheet to a specific PHP script. This script will open the stylesheet, and read it line by line to find and replace any user-defined variables. Finally the parsed content will be displayed as pure CSS; browsers won't notice the difference. To close this tutorial, we will also see how to cache the processed result to avoid unnecessary CPU usage.

Please note that some basic PHP (OOP), Apache and HTTP knowledge are expected.

Requirements:

  • Apache with Rewrite mod on
  • PHP 5

Step 1 - Build the Project

Let's first create our simple project structure. Add an index.html file to the root of your project.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Variables in CSS Files... It's possible!</title>
    <link href="css/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <h1>Variables in Stylesheets</h1>
    <p>It's possible!</p>
    <p>With PHP and Apache URL Rewrite Mod</p>
</body>
</html>

Now, create a CSS file with the following variables and place it in a "css" folder

$font: arial, sans-serif;
$main-color: #3D7169; $secondary-color: #000;

h1 {
    font: 200% $font;
    color: $main-color;
}
p { 
    background: $secondary-color;
    color: $main-color;
    font-family: $font;
    padding: 10px;
}

Finally, create a blank PHP file named enhanced_css.php and a blank .htaccess file. This latter file overrides the default configuration of the server and is applied to the folder and its subfolders.

Now our project should look like this:

Step 2 - Redirect CSS files to a PHP Script

We want to redirect any URL with a CSS extension to our PHP script. The Apache server allows us to do this by utilizing URL Rewrite mod. First, be sure that the "rewrite_module" modules is active on your server. Go and find the httpd.conf file in your Apache folder. Edit it and search for this line:

LoadModule rewrite_module modules/mod_rewrite.so

If needed, uncomment it by removing the prepended “#”, and restart Apache to make sure that your configuration settings are active.

Now, edit your .htaccess file and add the following lines.

RewriteEngine on
RewriteRule ^(.*\.css)$ enhanced_css.php?css=$0

Save it. As previously mentioned, the lines above ask Apache to catch all of the URLs with the .css extension and redirect them to "enhanced_css.php". The original CSS file path is passed in as a 'css' parameter.

For instance :

/css/styles.css 

Will be redirected to:

enhanced_css.php?css=/css/styles.css
Note:

Some hosting solutions don't allow their settings to be overrided by the user's ones. If so, the links to the stylesheets in the HTML code must be replaced manually.

In such instances, you will have to replace:

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

with:

<link href="enhanced_css?css=css/styles.css" rel="stylesheet" type="text/css" />

Step 3 - Parse the CSS file with PHP

Since the CSS files are redirected our PHP script, let's build a class named "Enhancedcss" to read them, find and replace variables, then display the contents as pure CSS. Our class will be instantiated by passing $_GET['css'] to the constructor. Remember the .htaccess redirection. $_GET contains the path to the current stylesheet.

if (isset($_GET['css'])) {
    $css = new EnhancedCss($_GET['css']);    
    $css->display();
}

The basic implementation of the class is composed of four methods. Later, we will add a caching method.

class EnhancedCss {
    public $values;
    public $cssFile;
    
    public function __construct($cssFile) {
        // check if the css file exists
    }
    
    private function parse() {
        // open the css file and throw every line to 
        // findAndReplaceVars method
    }
    
    private function findAndReplaceVars($line) {
        // find the variable definitions, store the values,
        // replace the variable by their defined values.
    }
    
    public function display() {
        // display the new parsed content        
    }
}    

The Constructor

Nothing sexy here. We check if the requested CSS file exists. If not, the script returns a 404 http error. The path of the CSS file is kept in the $this->cssFile property to compute the name of the cache file later.

public function __construct($cssFile) {
    if (!file_exists($cssFile)) {
        header('HTTP/1.0 404 Not Found');
        exit;
    }
    $this->cssFile = $cssFile;
}

The Parse Method

This method opens the CSS file and reads it line by line.

private function parse() {
    $content = '';
    $lines = file($this->cssFile);
    foreach($lines as $line) { 
        $content .= $this->findAndReplaceVars($line); 
    }
    return $content;
}

The file function is used here. It can be useful because it opens a file and returns the content as an array of lines. Each line is thrown to the findAndReplaceVars which processes the variables. The parsed content is then returned.

The FindAndReplace Method

This method is the primary workhorse of our class. It finds the variable definitions, stores theirs values in an array. When a variable is found, and if its value exists, it is replaced by the value.

private function findAndReplaceVars($line) {
    preg_match_all('/\s*\\$([A-Za-z1-9_\-]+)(\s*:\s*(.*?);)?\s*/', $line, $vars); 
    $found     = $vars[0];
    $varNames  = $vars[1];
    $varValues = $vars[3];
    $count     = count($found);    
                    
    for($i = 0; $i < $count; $i++) {
        $varName  = trim($varNames[$i]);
        $varValue = trim($varValues[$i]);            
        if ($varValue) {
            $this->values[$varName] = $this->findAndReplaceVars($varValue);
        } else if (isset($this->values[$varName])) { 
            $line = preg_replace('/\\$'.$varName.'(\W|\z)/', $this->values[$varName].'\\1', $line);
        }
    }
    $line = str_replace($found, '', $line);
    return $line;
}

Lots of code here. Let's review it in detail.

private function findAndReplaceVars($line) {
    preg_match_all('/\s*\\$([A-Za-z1-9_\-]+)(\s*:\s*(.*?);)?\s*/', $line, $vars);  

Here, we apply a regular expression to the current line. This expression matches and extract patterns like $variable:$value; (and some variants) or $variable in the current line. I wont go further here. Regular expressions are a complex topic which deserve an tutorial of their own. The Preg_match_all function returns all matches.

For example, the third line of our project's CSS file -

$main-color: #3D7169; $secondary-color: #000;

- will return this array:

$vars => Array 
(
    [0] => Array
        (
            [0] => $main-color: #3D7169;
            [1] => $secondary-color: #000;
        )

    [1] => Array
        (
            [0] => main-color
            [1] => secondary-color
        )

    [2] => Array
        (
            [0] =>  : #3D7169;
            [1] =>  : #000;
        )

    [3] => Array
        (
            [0] =>  #3D7169
            [1] =>  #000
        )
)

We assume that $vars[0] contains the complete match, $vars[1] contains the names of the variables, and $vars[3] contains the values. Let's organize the array to keep it clearer.

$found     = $vars[0];
$varNames  = $vars[1];
$varValues = $vars[3];

Now it's crystal.

$found => Array
        (
            [0] => $main-color: #3D7169;
            [1] => $secondary-color: #000;
        )
$varNames => Array
        (            
            [0] => main-color
            [1] => secondary-color
        )
 $varValues => Array
       (
           [0] =>  #3D7169
           [1] =>  #000
       )

We count how many variables have been found in the current line.

    $count = count($found);

This way we can cycle through each entry of our variables array. To make things clearer we set some new variables to handle the name and value.

for($i = 0; $i < $count; $i++) {
    $varName  = trim($varNames[$i]);
    $varValue = trim($varValues[$i]);            

    // ...
}

Variable Definitions

If $varValue is not empty, we're facing a variable defintion. So we have to store this value in the $this->values property.

if ($varValue) {
    $this->values[$varName] = $this->findAndReplaceVars($varValue);
} else if ...

Note that we pass the variable value in the findAndReplaceVars method again. This way, other potential variables will be processed as well. The values are stored in the $this->values array with the name of the variable as the key. At the end of the script, the $this->values array looks like this.

Array
(
    [font] => arial, sans-serif
    [main-color] => #3D7169
    [secondary-color] => #000
)

Variable Applications

If $varValue is empty, we're facing a variable application. We check if this variable exists in the values array. If it does, we replace the variable name by its value.

} else if (isset($this->values[$varName])) { 
    $line = preg_replace('/\\$'.$varName.'(\W|\z)/', $this->values[$varName].'\\1', $line);
}

This replacement might seem to be abnormally complicated. Actually no, this replacement takes care of replacing the $variable only if it is followed by a non character (\W) or an end-of-line (\z).

Finally, we remove the entire match to keep the stylesheet clean and valid. The processed line is returned.

    $line = str_replace($found, '', $line);
    return $line;
}

The Display Method

This method displays the parsed stylesheet. To be served to the browser as CSS content, the header is set to text/css content type.
public function display() {        
    header('Content-type: text/css'); 
    echo $this->parse();
}

Step 4 - Cache the Result

At this point, everything is working perfectly. However, the operation can be very CPU-consuming when used with larger websites.

After all, we don't need to parse the CSS files every time the browser needs it. The process only needs to be run the first time to create the cache, or if the original CSS file has been modified since the last caching operation. Otherwise, the previously rendered result can be reused. So, let's add a caching solution to our script.

Add a new folder named cache to the project. If needed, give this folder the right to be written in by applying a chmod 777. Now our project should look like this:

The Cache Method

A new method has to be added. Its function will be to :

  • read the cache file if it exists.
  • create and store the rendered results.
  • update existing cache file if the CSS file has been modified.

All the logic is handled by the method below:

private function cache($content = false) {
    $cacheFile = "cache/".urlencode($this->cssFile);
    if (file_exists($cacheFile) && filemtime($cacheFile) > filemtime($this->cssFile)) {
        return file_get_contents($cacheFile);
    } else if ($content) {
        file_put_contents($cacheFile, $content);
    }
    return $content;
}

Let's explain this code. The cache file name is computed from the original CSS file name previously kept in the $this->cssFile property. Finally, we use the urlencode function.

$cacheFile = "cache/".urlencode($this->cssFile);

That way a CSS file as

/css/styles.css

will be cached as

/cache/css%2Fstyles.css

We need to check if the cache file already exists, (file_exists) and if so, check if its creation date is not prior to the modification date (filemtime) of the CSS file.

if (file_exists($cacheFile) && filemtime($cacheFile) > filemtime($this->cssFile)) {
    return file_get_contents($cacheFile);

Otherwise, we create/recreate the cache file.

} else if ($content) {
    file_put_contents($cacheFile, $content);
}

Now the rest of the class must deal with this new method. Two methods need to be modified.

private function parse() {
    if (!$content = $this->cache()) {
        $lines = file($this->cssFile);
        foreach($lines as $line) { 
            $content .= $this->findAndReplaceVars($line); 
        }
    }
    return $content;
}

The parsing method now checks the cache before to run the whole process. If there is no cache available, the CSS file is parsed, otherwise the cached content is returned.

public function display() {
    header("Content-type: text/css"); 
    echo $this->cache($this->parse());
}

Finally, the method displays the right content (new or cached) provided by the caching method.

Browser Caching

For security reason (sessions, dynamic contents) browsers don't keep PHP results in their cache. A real CSS file would have been cached but not the result of our script. We have to deal with the browser to emulate the behavior of a real CSS file. Let's add some lines to the constructor.

public function __construct($cssFile) {
    if (!file_exists($cssFile)) {
        header('HTTP/1.0 404 Not Found');
        exit;
    }

    // Deals with the Browser cache
    $modified = filemtime($cssFile);
    header('Last-Modified: '.gmdate("D, d M Y H:i:s", $modified).' GMT');
	
    if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
        if (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $modified) {
            header('HTTP/1.1 304 Not Modified');
            exit();
        }
    }

    $this->cssFile = $cssFile;
}

We copy the last modification date of the original CSS file to our result in the header. Basically, headers are exchanged by browsers and servers before serving data. When the browser has a copy of a page in its cache, it send a HTTP_IF_MODIFIED_SINCE request to the server with the date previously given by header('Last-Modified', ...) the day it was cached. If the dates match, the content is up to date and doesn't need to be reloaded; so we send a 304 Not Modified response and exit the script.

A shorter way would be to simply add header('Cache-Control: max-age=3600'); to the file. The content will be cached 1 hour (3600 seconds) by any browser.

Conclusion

Done! You can now check one of your stylesheets on your server. For example, http://localhost/myproject/css/styles.css

$font: arial, sans-serif;
$main-color: #3D7169; $secondary-color: #000;

h1 {
    font: 200% $font;
    color: $main-color;
}
p { 
    background: $secondary-color;
    color: $main-color;
    font-family: $font;
    padding: 10px;
}

Becomes :

h1 {
    font: 200% arial, sans-serif;
    color: #3D7169;
}
p { 
    background: #000;
    color: #3D7169;
    font-family: arial, sans-serif;
    padding: 10px;
}

I hope you enjoyed this tutorial. What are your thoughts?


Related Posts

Check out some more great tutorials and articles that you might like

Enjoy this Post?

Your vote will help us grow this site and provide even more awesomeness

Plus Members

Source Files, Bonus Tutorials and
More for $9 a month for all TUTS+
sites in one subscription.

Join Now

User Comments

( ADD YOURS )
  1. PG

    Nouman Saleem March 18th

    I think its a little overkill to duplicate the css then use a variable when you can use snippets; HOWEVER, I LOVE this tutorial, so much learning involved. thanks!

    ( Reply )
    1. PG

      Hip Hop Makers March 19th

      I totally agree. Besides all this extra extra work you have to put in. I would be worried about possible errors that can happen. I like the concept though.

      ( Reply )
      1. PG

        Taylor Satula March 20th

        Ditto. Overkill

  2. PG

    Hassan March 18th

    Awesome! Very informative.

    ( Reply )
  3. PG

    Christian March 18th

    Great post, thank you!

    ( Reply )
  4. PG

    Lenny March 18th

    I don’t get how this is better than just using an include of styles (php driven page) at the top of every php page instead of importing an dynamically driven CSS file???

    ( Reply )
  5. PG

    Andy March 18th

    This is a great idea, I’ve actually been wondering about this for some time now. Only issue that I find is the css doesn’t validate. Bummer.

    ( Reply )
  6. PG

    iPad March 18th

    Wow, but to many work to achive this

    ( Reply )
  7. PG

    dvg March 18th

    Great tutorial … but why not just tell Apache to parse CSS as if it’s PHP?

    http://www.davidgagne.net/2008/10/01/parsing-php-in-css/

    I think it’s a bit easier … There’s only two things to do and then you can do all sorts of cool things in your CSS files …

    ( Reply )
    1. PG

      Ross March 29th

      I second that… just remember to get your php file (masquerading as css) to send the right headers and you’re sweet… much much easier than the tutorial above.

      ( Reply )
  8. PG

    Anthony Short March 18th

    This is very similar to the approach I’m taking with my framework, CSScaffold. It does variables, like in this tutorial, but a lot more. If you’re interested in this sort of method I’d suggest you check it out.

    http://wiki.github.com/anthonyshort/csscaffold

    And the video tut:

    anthonyshort.com.au/blog/comments/video-an-introduction-to-csscaffold/

    ( Reply )
    1. PG

      Jônatan Fróes March 19th

      Nice job, Anthony…

      ( Reply )
  9. PG

    Randy March 18th

    Nice article. This is one exception I would probably use inline CSS on a php page and simply insert a variable. Lots of useful info though, thanks!

    ( Reply )
  10. PG

    DKumar M. March 18th

    Ahhhh… Nice tips for CSS lovers. Thanks Jay for the round-up.

    ( Reply )
  11. PG

    Jeff March 18th

    I have a question.

    Why not simply create a php file, and have the php file echo out “header(‘Content-type: text/css’);” at the begining of the document. Then display css as normal, but throw in your variables as needed.. Seems like this would be an overall easier way to accomplish the same thing.

    ( Reply )
    1. PG

      gino March 19th

      This is the first thing that came to my mind reading.

      ( Reply )
    2. PG

      Jim March 19th

      Yep. I do something similar:

      1. using “”, have styles.css be a sym link.
      2. when developing or changing the site, point the sym link to ’styles.php’, which uses variables and other tricks, but has to be generated by the server
      3. when done, visit styles.css and save the generated output as styles.txt
      4. redirect the sym link to styles.txt

      Now you’ve developed with variables, but are serving static css files. This also works with mod-perl, python, etc. Toggling the sym link and overwriting the txt file with the generated output can be done with a couple trivial shell scripts.

      ( Reply )
  12. PG

    insic March 18th

    I dont get whats the point of making this lot of work just for css? But yes its a nice technique. Maybe the point of the author is to let the reader know that its possible to put variables in css file. :)

    ( Reply )
    1. PG

      crysfel March 19th

      i know, i prefer to do a find/replace instance of doing this, however the tutorial is good.

      ( Reply )
  13. PG

    Angel March 18th

    Great article, thank you!

    ( Reply )
  14. PG

    leaase March 19th

    What’s the difference between caching with php-script, and caching with .htaccess file like this:

    Header set Cache-Control “max-age=290304000, public”

    ??

    Great tut!

    ( Reply )
  15. PG

    tarya March 19th

    Great idea… Thank you!

    ( Reply )
  16. PG

    ashorlivs March 19th

    i’ve adopted jeff’s method for a while too and have never been disappointed.

    keypoint: as a project leader, you can for example ask your designers to change the dynamic color in no time. no need to opan many files, no need to know php, and barely css. just load the css and change the var (which you should all declare at the top and comment for non-coder audience)

    ( Reply )
  17. PG

    Shane March 19th

    Interesting angle.

    ( Reply )
    1. PG

      Shane March 19th

      Another way of doing it would be to separate out (or perhaps override) the aspects of the design that you wish to customise in another CSS file. The main file would contain everything but the things that you wish to tinker with.

      ( Reply )
  18. PG

    OSXBOY March 19th

    Bigest advantage of this method is the caching assuming you have a lot of complex CSS or need to have different CSS rules in different areas of a big site.

    ( Reply )
  19. PG

    Pelle March 19th

    I strongly suggest NOT to use this code, because it is very, very unsafe.

    Try requesting things like these:

    enhanced_css.php?css=enhanced_css.php
    enhanced_css.php?css=inc.db.php
    enhanced_css.php?css=/etc/passwd

    :|

    Jay, please adjust your code in the constructor, because it definitely is an example of how to write unsafe code, and I think most of the followers of this tutorial are not aware that this kind of security issues exist.

    ( Reply )
    1. PG

      Jay Salvat March 19th

      You’re absolutly right Pelle,
      I contact the administrator of Nettus right now for a patch.
      Thanks a lot to point at this security issue.

      Jay

      ( Reply )
    2. PG

      Jay Salvat March 19th

      Quick patch:
      Replace the line 2 of the constructor :

      if (!file_exists($cssFile)) {

      by this one :

      if (!file_exists($cssFile) || !ereg(‘.css$’, $cssFile)) {

      Jay

      ( Reply )
      1. PG

        N March 21st

        It would be much safer if you restricted all CSS files to a single directory.

        $filename = basename($cssFile);

        if(!file_exists($filename)) …

  20. PG

    jrheard March 19th

    If you’re looking to improve the CSS-writing process and have access to variables, you should check out Sass – http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html . You get mixins, your stylesheets make more sense, it’s pretty much just great all around.

    ( Reply )
  21. PG

    Benjamin Allen March 19th

    Great class, thanks for the tut – I can see this being very useful on a site with multiple colour schemes.

    ( Reply )
  22. PG

    François March 19th

    I’m not so fan. If the CSS is well done, we don’t have to repeat informations elements!

    But it’s interesting to know

    ( Reply )
  23. PG

    Martin Sarsini March 19th

    amazing! beginning reading I was thinking of commenting your article giving advice about a caching system… but you really thought about everything!

    ( Reply )
  24. PG

    Tarek Farage March 19th

    Thank you very much for this tutorial Jay!

    Its always nice to learn a new possibility to do things.

    ( Reply )
  25. PG

    Harry Roberts March 19th

  26. PG

    Vic March 19th

    Interesting tutorial

    ( Reply )
  27. PG

    kovshenin March 19th

    Wow! Great thanks!

    ( Reply )
  28. PG

    Jay Salvat March 19th

    Hi :)

    I agree that the method could seem complicated compared to some PHP basic solutions.

    The idea was to extend the behavior of CSS files to mimic a native, and as seamless as possible, var system to an existing project without breaking any webdesigner workflow.

    Renaming and relinking all the stylesheets from .css to .php iis not really natural… also, php files won’t be cached by browsers without any modification.

    ( Reply )
    1. PG

      Shelly March 19th

      I have to agree with some others – you can just use the “header” trick in the PHP file to pull this off. This tutorial’s a lot of overkill to accomplish something simple. As for renaming all the stylesheets – that’s not necessary either – since you can just use the PHP/variable stylesheet as just another stylesheet to add in the header and include it. Keep the base stylesheet for the regular” stuff, and use the secondary for the stuff that has variable interests.

      ( Reply )
  29. PG

    John McMullen March 19th

    Is there any benefit to this method compared to just adding a few lines of code to a jQuery .js file changing the specific attributes of your css?

    ( Reply )
    1. PG

      Dylan Anderson March 19th

      Well for one it works if the user has Javascript turned off.
      For two, it doesn’t require the user download an extra 20K file.

      ( Reply )
  30. PG

    Martyn March 19th

    I think this just went over my head, it seems that I’m missing something and there seems to be more easier solutions. I know its not major but I’ve also seen that someone says the css won’t validate?

    ( Reply )
  31. PG

    Allahverdi March 19th

    It’s very long way. But there is another way too:

    Then in php file, set: Content-type:text/css

    Now you can write your css code & your php code.

    ( Reply )
    1. PG

      Evan Byrne March 19th

      I second using this method over the one described in the article. Much faster and more secure.

      ( Reply )
  32. PG

    Timothy March 19th

    This is one of the best tutorials I’ve seen on here.

    It may only be useful in certain cases, since CSS tends to apply globally with no need of variables. But maybe with user-chosen themes or time-sensitive display changes it would be needed.

    ( Reply )
  33. PG

    Philo March 19th

    Great Article! :)

    ( Reply )
  34. PG

    JoeMama March 19th

    Agreed with dvg totally, just make your css files php executable. Very useful if your project contains a global configuration file. You can include that at the top of your css file and have all of your constants/cfg variable available in your css. If you don’t want to define headers in every css files you can do following in your apache conf or your vhost conf:

    php_value default_mimetype “text/css”

    it will still execute any php code in the style sheet and will send the correct header.

    ( Reply )
  35. PG

    JoeMama March 19th

    previous comment has some code formatting issues, so this is take 2:

    <FilesMatch "\.css$">
    php_value auto_prepend_file none
    php_value default_mimetype "text/css"
    </FilesMatch>

    ( Reply )
  36. PG

    Spongy March 19th

    You should take a look at compass http://wiki.github.com/chriseppstein/compass as an alternative to this method, plus it lets you semantically use Blueprint and the 960 grid system

    ( Reply )
  37. PG

    emson March 19th

    You could try SASS as an alternative:

    http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html

    ( Reply )
  38. PG

    Chris Pratt March 19th

    Good tutorial. I never thought about doing that before, but it’s definitely a clever idea. The only change I would make is to modify your PHP to hunt out true CSS variables (http://disruptive-innovations.com/zoo/cssvariables/). Variables are spec’ed in CSS, but not universally supported across all browsers. This way, the CSS file will be ready for the future and fully compliant for today with a little help from PHP.

    ( Reply )
  39. PG

    Arnaud Lemercier March 19th

    You can create an .htaccess file and write only :
    AddHandler application/x-httpd-php .css

    Your CSS file was parse with PHP.

    ( Reply )
    1. PG

      yaqoob March 19th

      would it be possible to apply AddHandler to only specific files and/or directories? forcing to process all css files around all website (lets say in wordpress installation with multiple plugins) would force you to add the header declaration to all these files around and that would be tiring to say least

      ( Reply )
      1. Yes, I fink it’s possible with :

        AddHandler application/x-httpd-php .css

  40. PG

    sky March 19th

    wow..it’s great..
    thank for your post

    ( Reply )
  41. PG

    Sean Hannan March 19th

  42. PG

    Patrick March 19th

    Dude, nice work…

    but… For me… too complicated, there’s a better way – you don’t need mod_rewrite, within the html-code you can easily link to the css file in this way:

    and i think it’s a better idea to parse an ini file with the color vars and then parse the css file with simple replacements – no regexes. The CSS File has some placeholders, p.e. __MAINCOLOR__, __FONTMAINCOLOR__ and so on.

    I think it would be much faster than your idea. And the css don’t have to be cached for performance reasons – it’s fast enough. If you want to, you can save the parsed css, read and print it out.

    ( Reply )
    1. PG

      Patrick March 19th

      Oh, i see now that the code was filtered out… Use as css link:

      link href=”css.php?css/styles.css” rel=”stylesheet” type=”text/css”

      And… Another important thing – check everything which comes from user – in this case it is a good idea to use a whitelist – read out the css directory and check which files are existing.

      ( Reply )
  43. PG

    Raphael Caixeta March 19th

    You can also try PHPMYCSS! http://phpmycss.com

    Great article nonetheless

    ( Reply )
  44. PG

    alex March 19th

    great article. Thanks. Parsing an css file as php is not a secure way if the css is not mean to be self-maintained. This method can prevent any abuse use of php in the css and allow designer to modify the css without concerning messing up the php. I like the idea of using the ini though.

    ( Reply )
  45. PG

    Andy March 19th

    If you need variables in your CSS you are probably doing it wrong! Learn how to write good CSS rather than write bad CSS and then write PHP code to work round it.

    ( Reply )
  46. PG

    Joel Gascoigne March 19th

    I’ve got to say, this is a nice article but I agree with many other people: I would probably go for making CSS be parsed as PHP:

    AddHandler application/x-httpd-php .css (in .htaccess)

    and then putting the correct header at the top in PHP:

    header(’Content-type: text/css’);

    ( Reply )
  47. PG

    Thibaut Allender March 19th

    Nice overkill demonstration :-)

    There are some far more simple solutions… ie:

    - Create a “css.php” file
    - Add at the beginning :

    - in style.css or secondfile.css, use or when needed…
    - call “css.php” only from your html

    That’s all !

    Pros:
    - concatenates your stylesheets -> only one http request
    - gzip the whole file -> smaller size sent to browser
    - handles browser cache (1 year)
    - no rewriting needed
    - doesn’t kill you webserver cpu

    Cons:
    - when changing something in the css files, hard reload or cache cleaning needed

    You can add something like ?version=1.0.0 to you css.php call to handle cache -> when you change something, increment your version.

    It could even be done automatcly using some filedate testing on the files to generate the css parameter automaticaly if your pages already use php.

    HTH.

    ( Reply )
  48. PG

    Thibaut Allender March 19th

    Sorry for the double post, tags were stripped, hope this one is OK, feel free to delete the previous one ;-)

    Nice overkill demonstration :-)

    There are some far more simple solutions… ie:

    - Create a “css.php” file
    - Add at the beginning :

    <?php
    ob_start(“ob_gzhandler”);
    header(‘Content-type: text/css’);
    header(“Expires: “.date(‘r’, mktime(0,0,0,date(‘m’), date(‘d’), date(‘Y’)+1)));

    $bg = ‘#fff”;
    $othervar = ‘10px’;

    include(’style.css’);
    include(’secondfile.css’);
    ?>

    - in style.css or secondfile.css, use <?php echo $bg; ?> or <?php echo $othervar; ?> when needed…
    - call “css.php” only from your html

    That’s all !

    Pros:
    - concatenates your stylesheets -> only one http request
    - gzip the whole file -> smaller size sent to browser
    - handles browser cache (1 year)
    - no rewriting needed
    - doesn’t kill you webserver cpu

    Cons:
    - when changing something in the css files, hard reload or cache cleaning needed

    You can add something like ?version=1.0.0 to you css.php call to handle cache -> when you change something, increment your version.

    It could even be done automatcly using some filedate testing on the files to generate the css parameter automaticaly if your pages already use php.

    HTH.

    ( Reply )
    1. PG

      Patrick March 19th

      yet another nice idea. But you shouldn’t use the expire Header, could be a bit problematic and (more important) useless when browsercache is disabled. As i know, Browsers cache files with more data than only the expire code. Most Browsers load files from a server again if the filesize is different from the cached file, so i think it’s irrelevant to set the expire-header.

      ( Reply )
  49. PG

    Seth March 19th

    Does this affect the speed of the download time? How quickly does the site load now that you are parsing the CSS first and then displaying it?

    ( Reply )
  50. PG

    Soner Gönül March 19th

    it’s amazing..

    ( Reply )
  51. PG

    rob March 19th

    Overkill plus using the wrong technology to solve a problem!

    if you put an Id on the body of your pages. you can define seperate css for a given page and css that is common.

    This way when work ing with a design person they don’t have learn your tagging system for variables.

    respect css it’s plenty powerful as is and doesn’t need rewriting. that how we got flash …

    ( Reply )
  52. PG

    Unknown March 19th

    This is to much :)
    why not use sass :)

    http://lab.hamptoncatlin.com/play/with/sass

    ( Reply )
  53. PG

    Chris March 19th

    Awesome TUT. Sadly you don’t always have .htacces acces.
    I mostly use jQuerys DOM Manipulation capabilities.

    ( Reply )
  54. PG

    paul March 19th

    thank you so much. ive been wanting to do this for ages, but never found a good and simple solution, everything included rewriting files all over the place and my security conscience boss was never gonna go for it.

    this is rad!

    ( Reply )
  55. PG

    Merijn March 19th

    Its nice, however, having to rewrite the entire css on every new page with new content, takes up time. You also send more headers then necesary. I believe that all styling can be achieved through CSS only. Basiing it on a html with class, body with class, and so on. This way, you can have many different options.

    And the stylesheet might be bigger, however, you only have to cache it once, and its sending only 1 header to the browser. Besides, character encoding on Firefox ( which is actually one of the slowest..) parses 250,000 characters in about 0.7 mili seconds.

    ( Reply )
  56. PG

    Lowkase March 19th

    What is the main advantage of this approach? Please, I am at a loss for what advantage this technique could possilby provide considering the performace hit you are going to take on the parsing side.

    The solution is extreme overkill that hinges on the web server being Apache and the fact you need access to the mod_rewrite funtion on the apache server. Most of us doing freelance work don’t have that kind of control granularity on the server side.

    I have to agree with other here, I think you are misusing CSS and hacking in a very complex and possibly insecure solution.

    Personally, I just override CSS attributes by using inline CSS on my template.php file. I can grab values from a database, xml file, array, etc and use inline CSS after the CSS includes on the template to allow for site wide dynamic CSS effects.

    /shrug.

    Cheers,

    Lowkase

    ( Reply )
    1. PG

      Dave Nicoll March 21st

      This could easily be done in ASP.NET with the URL rewriter/ionic rewriter

      ( Reply )
  57. PG

    Kangaroo_Deziner March 19th

    I think I might be a little lost. Can someone explain to me the point for this?

    It seems like you’re just plugging in a variable like $font instead of “Arial, Helvetica, sans-serif”, and then using a parsing function to change all instances of $font to “Arial, Helvetica, sans-serif”. Is that correct?

    I can see that if you wanted to change the font you’d just change the $font to “Verdana” or whatever you’d just change it in one place and then the PHP would do the rest, but how is that any different from a Find/Replace?

    I’m just not sure I see the use.

    ( Reply )
  58. PG

    mydarb March 19th

    Next up, killing mosquitoes with rocket launchers!

    ( Reply )
  59. PG

    Nico March 20th

    This is not really, the way to save some work Time, it takes too much time to code for just a few colors.

    ( Reply )
  60. PG

    Rafi B. March 20th

    I would use the htaccess trick, but great article nonetheless! It inspired a good discussion here, and showed really good code snippets.

    ( Reply )
  61. PG

    joe March 20th

    I definitely RTFA but did I miss the part about WHY you’d want to do this? Besides, of course, providing an alternative to inline CSS, that is.
    else, good article.

    ( Reply )
  62. PG

    David Singer March 20th

    I love it.

    One tip allow the class to take multiple files then combine them/compress them (there is open source code for this already)/cache them. That way if a developer needs to load 10 css files there is only one http request.

    ( Reply )
  63. PG

    Srikrishna March 21st

    Excellent article.

    Thanks a lot for this

    ( Reply )
  64. PG

    Dave Nicoll March 21st

    WHY? This technique has been possible for ages but generally isn’t used because anyone with the required coding skills to knock this up understands how to seperate the different styles to create a CSS framework capable of skinning sites.

    Also there’s a typo-where you have the code snippet to insert the CSS reference into the HTML for non-rewritten URLs, you’ve missed the .php ectension.

    ( Reply )
  65. PG

    Remiz March 21st

    Same technique is used in a job portal script which I came across a year ago. But that was using css inside php file itself. Here same thing is done but redirected using htacess . Any way, nice post which included too many studies .

    Cheers

    ( Reply )
  66. PG

    Marco P March 21st

    This article is misleading. That method is too much for a simple thing. I seriously think that the quality of the articles are declining.

    ( Reply )
  67. PG

    Eric March 21st

    People who don’t see the point of this can’t possibly have made a large CSS file EVER. This is EXCELLENT to keep consistency within your document, and being able to change things quickly when testing out different stuff.

    It’s not used for managing different pages’ CSS, it’s used to define all common properties that you might want to change in an easy accessable place that changes all the appropriate places in one go.

    Oh, and to all the “just make it a php file”-people: It might work the same way, but then you’d need a php starting tag and an echo statement with ” ” around it, messing up code highlighters. And then it doesn’t feel like CSS. With Jay’s solution it feels like CSS, only with variables. Thanks Jay! :)

    ( Reply )
  68. PG

    Tuan Anh March 21st

    I love the idea of this article. It looks like a PHP Template Engine for CSS, and if we look deeply inside it, it’s very like Smarty, but, of course, it’s very light and small in compare with other PHP template.

    But in reality, I wouldn’t do this way :D . I like separating CSS into files and dynamical including them.

    ( Reply )
  69. PG

    Adam March 21st

    Why wouldn’t you just point your css link in the head of your html page to a .php instead of a .css file?

    All you have to do is drop in this one line in the top of the .php file
    and you can use php variables etc. just like normal.

    Any thoughts?

    ( Reply )
    1. PG

      Adam March 21st

      Sorry for the repost. But this didn’t come through on my first post. header(“Content-type: text/css”)

      ( Reply )
  70. PG

    amidude March 23rd

    Correct me if I’m wrong but doesn’t this prevent the separation of the presentation and application layer?

    ( Reply )
  71. PG

    thomas wornall March 23rd

    this is one of those articles it would be nice to print and have the comments as well as the article.

    ( Reply )
  72. PG

    Martin Gonzalez March 24th

    Very nice and very useful
    Thanks mate!

    ( Reply )
  73. PG

    Mighty Uhu March 25th

    Actually I cannot see any sense in implementing variables over a php handler with a template system and caching.
    Besides in my humble opinion this method is some kind of overkill at all, with a clear css structure there is no need for variables at all. If you want a dynamic CSS, you should consider this when creating it. CSS implements this nice feature of global inheritance of properties. You also have the option to bundle the propertyset of elements.

    ( Reply )
  74. PG

    Adryi19 March 25th

    Awesome Thanks. For Share

    ( Reply )
  75. PG

    chandrakant March 26th

    Nice tut

    ( Reply )
  76. PG

    quocvuong March 30th

    Thank you

    ( Reply )
  77. PG

    Max April 6th

    Thanks for the info! A big help in the work

    ( Reply )
  78. PG

    The Baldchemist April 22nd

    Jay, after 12 years on the Internet nothing you do should be modest!
    Modesty these days is mediocre, this is far from that my friend.
    Just because we have become used to comfortable mediocrity you dont need to support it. You have stated your case, dont you think it stands out above the rest?
    Its one thing being able to crunch the codes but filling in with interesting, compelling copy requires a little more. But, many thanks for your very interesting article.
    Keep well and get as much joy as you can every day.

    ( Reply )
  79. PG

    Mike April 26th

    There is one thing that several of you ‘just make it a php page’ people probably dont know, There is a extremely annoying issue with IE and it deciding not to render the output of the php page correctly – or at all (most often on the first load), thus using this technique is brilliant.

    Well done Jay, Very nice article.

    ( Reply )
  80. PG

    Amr Hussien May 10th

    very cool tut, i really enjoy it since i am advance with the CSS

    ( Reply )
  81. PG

    Martin Leblanc May 14th

    Great tip, but why not go all the way and use a framework like Compass?

    ( Reply )
  82. PG

    WallpaperDude May 18th

    Really awesome, just seems like it over-complicates things.

    ( Reply )
  83. PG

    Lakin Wecker May 26th

    I’m always astounded by how many people write parsers in PHP? For heaven’s sake – PHP _is_ a templating language. It’s ENTIRE design is built around the concept of outputting text files based on input variables. For instance to dynamically generate the above css file just use:

    h1 {
    font: 200% ;
    color: ;
    }
    p {
    background: ;
    color: ;
    font-family: ;
    padding: 10px;
    }

    What is the point of writing a new parser? Especially if it’s driven by a forloop and regex. It’s likely to be more buggy, and less featureful than PHP proper. For instance – simple math expressions:

    h1 {
    margin-left:
    }

    You can get simple caching to avoid regenerating it via all sorts of methods built into HTTP – use an expires header that sets the expiry date into the future 10 years and then always use a simple GET var in the link tag. If the GET var is based on the date, and you only change it when the CSS changes, then the browser will _never_ request the CSS again until you change that date var – so no processing on the client side.

    If you really need the full server side caching you can get it by using a similar class, combined with mod_rewrite – but instead of a new, made-up syntax use PHP to do the parsing and interpretation.

    ( Reply )
  84. PG

    Roger June 20th

    Would using “AddHandler application/x-httpd-php .css” allow to browsers to cache the css?

    ( Reply )
  85. PG

    khoe September 17th

    This is a big no no. Presentation should be decoupled from any server-side logic. You can do this much easier and cleaner by simply using CSS specificity. Have a base CSS and switch on a second CSS to override template-specific styles.

    ( Reply )
  86. PG

    Rodolfo Sánchez October 3rd

    It’s usefull when you have to replace things like an url base. IE:
    #polaroids { background: url($base/img/polaroids.jpg) no-repeat right center; }

    Thanks Jay. Greatings from Argentina!

    ( Reply )
  87. PG

    Greg October 12th

    Thanks for the tutorial, Jay! I apologize on behalf of the world for the huge number of people that didn’t “get it”. ;-) I won’t lie and say I’m rushing out to implement this, but I can understand the goals, and if you’re trying to solve a particular problem, it’s not necessarily “overkill” as some have claimed!

    ( Reply )
  88. PG

    hostel zakopane October 18th

    Ahhh!
    Nice tips :) Great idea… Thank you!

    ( Reply )
  89. PG

    David Southwell October 19th

    Really interesting now how about a parsing tool that extracts all potential variables in existing .css and databases them alongside the values that actually occur in the .css. At the same time produce a copy of the .css with the existing value replace by a $xxxx. This file is now on the way to becoming an enhanced .css file.

    Ok now if we could use the database to generate an interactive tool for configuring all .css files in an application we would have an extremely valuable tool that would convert all those web applications that are so difficult to manage into simply configurable applications.

    Does this make sense??

    ( Reply )
  90. PG

    mrak911 November 10th

    Very cool tut, i really enjoy it since i am advance with the CSS

    ( Reply )
  91. PG

    Taylor Satula December 3rd

    I haz tah love for this article. Thank you. It’s what I was just looking for

    ( Reply )
  92. PG

    marcus December 13th

    lol@ the 1000 comments “parse css as php set header xyz blabla”
    I like this method because it keeps my css as it is but enhance it with that nice var stuff, doesn’t broke the syntax highlighter in my editor with tags in css files, cache the styles and after I extend it to parse @import rules and add whitespace compression I can keep my modular structure and just have just one single request on productive system.

    There is just the security thing to fix. You can find it in the middle of the comments.

    The mentioned Sass css parser is the real overkill.
    for me it complicates CSS with new syntax to learn and beside organisation of code, it makes it hard to find bugs if you check back with firebug and try to find the line in your sass files (as far as I understand the system)

    thats my 3 cent :P

    ( Reply )
  93. PG

    Dratutsmits December 18th

    Como el especialista, puedo prestar la ayuda. Juntos podemos llegar a la respuesta correcta. http://nuevascarreras.com/comprar-cialis-es/ cialis 20 mg wikipedia Che cosa audacia! comprar cialis original

    ( Reply )
  94. PG

    e11world January 11th

    This is very interesting and I’d like to see how things will change on this subject in the next 3 years. I want to say it will be bigger but I’m just not sure.

    ( Reply )
  1. Arrow
    Gravatar

    Your Name
    January 11th