Generating Dynamic CSS with PHP
Published on April 28, 2005
I can certainly relate to this as a programmer—it was one of the first things I thought of when I started using CSS. Because I prefer to separate my work into discrete modules, I immediately recognized the power behind the concept. I was already using PHP, Perl and other tools to generate HTML dynamically, so CSS didn’t seem quite powerful enough. However, it didn’t take me long to learn how to approach style sheets in a similar way.
CSS is designed for layout and presentation. Its goal is to restore HTML documents to their original purpose—to be structural in form and to reflect the flow of the content contained in them. In the brave new world of XHTML, this is mandatory.
Want to impress your geek friends? Mention that CSS isn’t even close to being Turing complete. It’s true—CSS has no concept of variables, conditions, loops or many other features inherent in programming languages. The trick is to dynamically generate style sheets using a language that does have these properties. By now, even non-programmers have heard of PHP.
PHP’s penetration into the Web server-side scripting market share is remarkable, and it overtook Microsoft’s ASP three years ago as the top language used by developers. It typically runs on the Apache HTTP server, the most popular server on the Web.
One reason for this explosive growth is that PHP is free and open source. It’s also a relatively easy language to learn and the de facto standard for developers creating dynamic Web pages. But it is also perfectly suited for deploying CSS and many other Web technologies.
To demonstrate this technique I will design a mock up of a basic site layout using CSS. It will include a masthead, menu and content area. I will then assign three color schemes using PHP for the background and foreground colors of each element in the layout and show you how you can easily switch between each one or add new schemes—all from one script. I’ll conclude the article by suggesting ways you can extend or improve on these ideas for your own site.
PHP is an embedded technology, meaning you can combine the logical/programming code with normal HTML or XHTML markup. In a more general sense, the output can be any text you like—in this case, it’s CSS. To toggle between these two modes you simply use special start and end tags:
/* PHP code... */
/* ... */
You can also send code back to the browser using output functions such as
echo(). There are a number of other methods, but I will be using a variation on the
print() function known as "heredoc syntax" to return first the persistent style sheet then each alternate.
Before doing anything we must tell the browser what resource type we’re returning. Normally, PHP and the Web server it’s running under will automatically tell the browser that a PHP script is HTML. In the case of a static CSS file, the server knows it’s CSS by the file extension. But this is a special case, so our first job is to send the correct media, or MIME type to the browser using the PHP
The next step is to define the color scheme sets using associative arrays. An associative array is just a collection of related items, each accessed by a string. Normal arrays use an integer-based index. It’s just another type of variable, and all variables are prefixed by the dollar sign. So, the first of our color schemes, the default or persistent style, is defined like this:
$persistent = array(
'bgmast' => 'bbd9ee', /* masthead */
'fgmast' => '4d4d4d',
'bgmenu' => 'e7e4d3', /* menu */
'fgmenu' => '444',
'bgcont' => 'fff', /* content */
'fgcont' => '444' );
Notice I’m using hexadecimal color values here and not including the pound sign (#) in the color values. We’ll take care of that when we output the CSS code. To reference one color in the array you address the
$persistent array using the named or string index. For instance, the value for the masthead background color can be accessed like this:
print $persistent['bgmast']; /* output: bbd9ee */
Note: You will see a slight variation on this syntax when we actually use it in the dynamic style sheet. This is due to a conflict between the PHP parser and the CSS code that surrounds it.
If you take a look at the PHP source code in the dynamic style sheet, you’ll see that just as in the example above, I’ve defined two alternate color schemes. Now it’s just a matter of finding a mechanism to select each the three versions.
HTTP GET and the Query String
You’ve seen the funny-looking URIs that contain a question mark followed by
name=value pairs separated by ampersand (
&) characters at the end. When you click on a link (an anchor or
<a> element) in a Web page, you’re using the
HTTP GET method (
POST is used for submitting forms). The extra bits on those URIs that have them are a way of passing variables to the script, and the entire thing is called a query string. PHP allows you to access these names and their values from a global associative array called
This is exactly how we can request variations from the style sheet script. To do this we call it three times from
<link> tags in the
<head> element of the HTML document. The first one is for the default or persistent style sheet, so it requires no query string. The subsequent two requests for the same script will return variations in the form of our alternate color schemes.
<link> elements begin with the same attributes:
<link type="text/css" media="screen"
Followed first by the persistent style sheet:
rel="stylesheet" href="css-demo.php" />
which has a
rel (relationship) attribute of "stylesheet" and no title attribute or query string variable, and then the two alternates:
rel="alternate stylesheet" title="Color Scheme #1" href="css-demo.php?scheme=alt1" />
rel="alternate stylesheet" title="Color Scheme #2" href="css-demo.php?scheme=alt2" />
which have a
rel of "alternate stylesheet" and do have titles and query strings.
Let’s get back to the script. We know if the browser calls
css-demo.php and there is no value for
$_GET['scheme'] then this is the persistent style sheet, so we return the basic visual rules for the
<div> elements that define the mock up followed by the default color scheme. Otherwise, we select from one of the two alternates and only return the color values. This is where the "cascading" part comes in. Since everything else is already declared, all we have to do is return the alternate color sets. As all three are downloaded and cached by the browser when the HTML document is first requested, when you select a different scheme the effect is instantaneous.
To make this clearer, have a look at these resources:
- Source code of the PHP/CSS script
- Resulting CSS for the persistent style
- Results for Alternate Color Scheme #1
- Results for Alternate Color Scheme #2
Now let’s have a look at the script in action. First, the mock up using the persistent style:
Paragraph element here, just to fill out the area somewhat.
Now to make the switch. There are two approaches. If your browser supports it, you can use the interface it provides. There may be an option under the "View" menu, something like Page Style, Style or Use Style, and under that option you will see the alternate styles listed by the titles we gave them in the
<link> elements as described earlier. Give it a try.
- Alternate Color Scheme #1 (W3C CSS)
- Alternate Color Scheme #2 (Author’s Selections)
- Reset Persistent Style (Digital Web Magazine)
Because no browser that I’m aware of will remember that you prefer an alternate style, and also because the HTTP protocol is by design stateless, this technique does have one major drawback—the effect is temporary. To see what I mean, select an alternate style, then refresh the page or move to another one and then back again.
There are ways around this problem, and many possibilities beyond this simple color switcher—for example, a membership site where users can select from any number of colors, fonts and layouts. Since you are already identifying users when they log in, returning preferred style sheets would be a snap. Or perhaps you’d like to offer an interface to sight-disabled users that has better contrast, larger fonts, and so on. For a public site, it’s possible to save this preference as a cookie on users machines for the next time they visit.