Supercharge Your CSS with PHP Under the Hood

August 25th, 2009 | by admin |

Cas­cad­ing Style Sheets is a pre­sen­ta­tional style sheet lan­guage. In that sense, it does not have a lot of the func­tion­al­ity that many devel­op­ers want to sat­isfy their pro­gram­mer instincts. Today, we’re going to go over how to super­charge your CSS by putting some PHP under the hood.

Tuto­r­ial Details

  • Pro­gram: Apache, PHP
  • Ver­sion: n/​a
  • Dif­fi­culty: Intermediate
  • Esti­mated Com­ple­tion Time: 20 minutes

Intro­duc­tion

Using CSS to power up a web­site is a req­ui­site in the con­tem­po­rary web for non-​​Flash web­sites – and for good rea­son. CSS is pow­er­ful. It can make or break a web­site (although usu­ally IE6 is doing the break­ing). Even with its use­ful­ness, design­ers and devel­op­ers alike have have wished for more out of the lan­guage since its incep­tion over twelve years ago with the CSS Level 1 Rec­om­men­da­tion. Today, we’re going to review some ways to Super­charge Your CSS With PHP Under The Hood.

Supercharging XHTML/CSS

Note: I am not going to be argu­ing for or against the con­cept of CSS Vari­able and/​or CSS Con­stants. This arti­cle is writ­ten with the assump­tion that you will make an informed deci­sion regard­ing these once pre­sented with what it can do. This arti­cle teaches how to set them up and use them, but does not address the con­tro­versy in full.

Set­ting Things Up

Before the super­charg­ing begins, we have to ensure that you have the proper require­ments for doing so. We are going to go over two meth­ods of mak­ing your CSS work with PHP, one that is short and sweet, and one that is a bit more ele­gant and less notice­able to the user. Both of these have the same basic require­ment of a server run­ning PHP. The more ele­gant ver­sion requires a bit more:

  1. Apache (run­ning PHP, obviously)
  2. An editable .htac­cess file

Set­ting Up the Sim­ple Method

Web browsers are not that picky about file exten­sions when deal­ing with the HTML link tag. What they are picky about is the header data that it receives for that file. What that means is that you can link a *.php file with the proper header data in the place of a *.css file, and the browser will inter­pret the result just like stan­dard CSS. To do so, add the PHP header that tells Apache to out­put the file as CSS:

<?php header("Content-type: text/css; charset: UTF-8"); ?>

Then, just link to the PHP file like you nor­mally would:

<link rel="stylesheet" href="css/supercharged.php" media="screen">

Now that you have done this, you can–in theory–skip to the next sec­tion of the tuto­r­ial deal­ing with CSS vari­ables and con­stants, if you would like; how­ever, any­one who views your source is going to see that you have a PHP file where a CSS file should be. Addi­tion­ally, just because the browser will inter­pret the result prop­erly does not mean that it will nec­es­sar­ily do other things like caching the file in the browser. To fix this, we move on to the slightly more ele­gant version.

Set­ting Up the Ele­gant Method

Apache comes with a large num­ber of .htac­cess tricks. This is one of them. We are going to tell Apache to inter­pret all CSS files in a cer­tain folder as PHP files, and the web browser (and your users) will, gen­er­ally speak­ing, not know that you are doing so. First thing to do is to put the header data in your CSS file, just like the Sim­ple Method:

<?php header("Content-type: text/css; charset: UTF-8"); ?>

Then, instead of sav­ing the CSS file as a *.php file, you save it as a *.css file, and you place it in a folder for CSS (in our exam­ple, ~/​css/​). Once you have done this, cre­ate a *.htac­cess file in that folder and add the following:

AddHandler application/x-httpd-php .css

This snip­pet tells Apache to inter­pret all CSS files in the folder with the *.htac­cess file with the PHP script han­dler. If you do not have the abil­ity to add this to a sin­gle folder or if you need this to be server­wide, you can also add this to the httpd.conf server con­fig­u­ra­tion file for Apache. To do so, you would want to add the pre­vi­ous snip­pet right below the group of AddType and AddHan­dler dec­la­ra­tions (like these from one of my servers):

AddType application/x-httpd-php .php .php3 .php4 .php5
AddType application/x-httpd-php-source .phps
AddHandler cgi-script .cgi .pl

Just remem­ber that if you do add this to your httpd.conf server con­fig­u­ra­tion file that EVERY *.css file on the server now must have the PHP header for text/​css prepended to it. This is why my rec­om­men­da­tion is to add it via .htaccess

Start the Engine with CSS Variables

From the Aver­age Top 100 Weblog Per­for­mance Sur­vey:

We ran a test on the top 100 blogs for exter­nal CSS files and total size. The aver­age top 100 blog uses 4 exter­nal CSS files (@imports included) with an aver­age total file size of 43.1K (uncom­pressed). The num­ber of exter­nal CSS files ranged from 1 to 18. The total size of CSS ranged from to 0.2K to a whop­ping 307K. Note that this analy­sis does not include inter­nal CSS within (X)HTML files. It does include nested CSS files called with @import directives.

That is a lot of CSS. Why is this? A lot of times it is because the CSS is being deliv­ered uncom­pressed and not opti­mized. The more likely sus­pect is CSS bloat and poorly main­tained code. One pop­u­lar option to improv­ing code main­tain­abil­ity is to imple­ment CSS Vari­ables through PHP.

What this means is that instead of hav­ing CSS like this (yes, this would pro­duce an aber­ra­tion of design, but it’s good at illus­trat­ing the point):

body {
 color: #000;
 background: #fff;
 font-size: 10px;
}
div#content {
 background: #ccc;
 font-size: 1.1em;
}
div#sidebar {
 color: #fff;
 background: #000;
 font-size: 1.0em;
}
div#footer {
 color: #555;
 background: #ccc;
}

You could have CSS like this:

<?php
$primaryTextColor = '#000';
$secondaryTextColor = '#fff';
$tertiaryTextColor = '#555';
$primaryBGColor = '#fff';
$secondaryBGColor = '#ccc';
$tertiaryBGColor = '#000';
$primaryTextSize = '10'; //pixels
?>
body {
 color: <?=$primaryTextColor?>;
 background: <?=$primaryBGColor?>;
 font-size: <?=$primaryTextSize?>px;
}
div#content {
 background: <?=$secondaryBGColor?>;
 font-size: <? echo 1.1*$primaryTextSize ?>px;
}
div#sidebar {
 color:  <?=$secondaryTextColor?>;
 background: <?=$tertiaryBGColor?>;
 font-size: <?=$primaryTextSize;?>px;
}
div#footer {
 color: <?=$tertiaryTextColor?>;
 background: <?=$secondaryBGColor?>;
}

Note that the long vari­able names is for illus­tra­tion pur­poses only. Obvi­ously, these vari­ables can be as long as or as short as you like, and shorter vari­ables make for smaller file sizes.

In the exam­ple above, we have used basic vari­ables to set up a mono­chrome color scheme that could then be used through­out the web­site in other styles. These vari­ables could eas­ily have been inter­changed with $color01, $color02, $color03, etc to pro­duce sim­i­lar effects. Often, design­ers and front-​​end web devel­op­ers get asked by clients “Hey, can you make all of the text a lit­tle darker?” or “Can you make all of the text just a lit­tle big­ger?” While using vari­ables like this will not always be the best solu­tion, it often would reduce the main­te­nance time when using many tem­plat­ing sys­tems and blog­ging plat­forms (Word­Press, Move­able Type, Expres­sion Engine, etc) or cor­po­rate CMSes (Dru­pal, Joomla, Bitrix, etc).

An alter­na­tive method of stor­ing the vari­ables is to store the data in asso­ciate arrays (which is my pre­ferred method), which pro­duces code more like the following:

<?php
$defaultCSS = array(
 'color01' => '#000',
 'color02' => '#fff',
 'color03' => '#ccc',
 'color04' => '#555',
 'baseTextSize' => '10'
);
?>
body {
 color: <?=$defaultCSS['color01']?>;
 background: <?=$defaultCSS['color02']?>;
 font-size: <?=$defaultCSS['baseTextSize']?>px;
}
div#content {
 background: <?=$defaultCSS['color03']?>;
 font-size: <? echo 1.1*$defaultCSS['baseTextSize']; ?>px;
}
div#sidebar {
 color:  <?=$defaultCSS['color02']?>;
 background: <?=$defaultCSS['color01']?>;
 font-size: <?=$defaultCSS['baseTextSize'];?>px;
}
div#footer {
 color: <?=$defaultCSS['color04']?>;
 background: <?=$defaultCSS['color03']?>;
}

Cal­cu­la­tions in CSS

Once you have set things up for using PHP with your CSS, you can then do some neat things like cal­cu­la­tions. Let’s assume that you want to set up a sys­tem in you pro­vide a bunch of DIVs on screen, each with a dif­fer­ent type of ele­ment inside. Each ele­ment type (i.e. img, p, block­quote, etc) has a unique height and width con­trolled via CSS, and you want the amount of mar­gin to be based off these val­ues like so:

Diagram of Padding / Element Measurements

In this sce­nario, you want to set up a stan­dard­ized grid that con­tains three dif­fer­ent types of ele­ments (img, p, and block­quote) encap­su­lated in two dif­fer­ent con­tain­ers (div and li). Every DIV has to be 550px wide and 250px tall, every LI has to be 600px wide and 300px tall, and each of the ele­ment types has a dif­fer­ent height and width. The posi­tion­ing of the ele­ments on the inside must be dead cen­ter. Over time, the heights and widths of the dif­fer­ent DIVs/​LIs and ele­ments will likely need to be changed. You could man­ual enter the amount of mar­gin for each of the dif­fer­ent ele­ments and/​or use extra class infor­ma­tion on the con­tainer DIVs to add the appro­pri­ate amount of padding, but this is not that use­ful for quick changes, like those wanted by some­one who is pro­to­typ­ing in the browser or who has 200 of these dif­fer­ent ele­ments for which they would have to mod­ify data.

Step 1 – The Structure

First, we set up the XHTML con­tent that we are going to style like so:

<div><p>Lorem ipsum dolor sit amet tellus.</p></div>
<div><blockquote>Etiam quis nulla pretium et.</blockquote></div>
<div><img src="images/inset.png" alt="Inset Image" /></div>
<ul>
<li><p>Lorem ipsum dolor sit amet tellus.</p></li>
<li><blockquote>Etiam quis nulla pretium et.</blockquote></li>
<li><img src="images/inset.png" alt="Inset Image" /></li>
</ul>

Step 2 – The PHP Header and Vari­able Declarations

Next, we set up the PHP/​CSS file that we are going to use to style the XHTML. This is where we declare the stan­dard sizes of the dif­fer­ent ele­ments for use through­out the page.

<?php
header("Content-type: text/css; charset: UTF-8");

$divData = array(
 'width' => '550',
 'height' => '250',
);
$liData = array(
 'width' => '600',
 'height' => '300',
);
$blockquoteData = array(
 'width' => '440',
 'height' => '100'
);
$imgData = array(
 'width' => '450',
 'height' => '150'
);
$pData = array(
 'width' => '480',
 'height' => '130'
);
?>

Step 3 – The CSS with Vari­ables and PHP Calculations

Next, we con­tinue the PHP file from Step 2 and uti­lize the vari­ables that we set in cal­cu­la­tions. Addi­tion­ally, we set the cal­cu­lated Mar­ginX and Mar­ginY val­ues of the dif­fer­ent ele­ments to reduce the num­ber of cal­cu­la­tions necessary.

div {
 width: <?=$divData['width']?>px;
 height: <?=$divData['height']?>px;
}
li {
 width: <?=$liData['width']?>px;
 height: <?=$liData['height']?>px;
}
div blockquote {
 width: <?=$blockquoteData['width']?>px;
 height: <?=$blockquoteData['height']?>px;
 <?
  $blockquoteData['divMarginX'] = $divData['width']-$blockquoteData['width'];
  $blockquoteData['divMarginY'] = $divData['height']-$blockquoteData['height'];
 ?>
 margin: <? echo blockquoteData['divMarginY']/2; ?>px <? echo blockquoteData['divMarginX']/2; ?>px;
}
div img {
 width: <?=$imgData['width']?>px;
 height: <?=$imgData['height']?>px;
 <?
  $imgData['divMarginX'] = $divData['width']-$imgData['width'];
  $imgData['divMarginY'] = $divData['height']-$imgData['height'];
 ?>
 margin: <? echo imgData['divMarginY']/2; ?>px <? echo imgData['divMarginX']/2; ?>px;
}
div p {
 width: <?=$pData['width']?>px;
 height: <?=$pData['height']?>px;
 <?
  $pData['divMarginX'] = $divData['width']-$pData['width'];
  $pData['divMarginY'] = $divData['height']-$pData['height'];
 ?>
 margin: <? echo pData['divMarginY']/2; ?>px <? echo pData['divMarginX']/2; ?>px;
}
li blockquote {
 width: <?=$blockquoteData['width']?>px;
 height: <?=$blockquoteData['height']?>px;
 <?
  $blockquoteData['liMarginX'] = $liData['width']-$blockquoteData['width'];
  $blockquoteData['liMarginY'] = $liData['height']-$blockquoteData['height'];
 ?>
 margin: <? echo blockquoteData['liMarginY']/2; ?>px <? echo blockquoteData['liMarginX']/2; ?>px;
}
li img {
 width: <?=$imgData['width']?>px;
 height: <?=$imgData['height']?>px;
 <?
  $imgData['liMarginX'] = $liData['width']-$imgData['width'];
  $imgData['liMarginY'] = $liData['height']-$imgData['height'];
 ?>
 margin: <? echo imgData['liMarginY']/2; ?>px <? echo imgData['liMarginX']/2; ?>px;
}
li p {
 width: <?=$pData['width']?>px;
 height: <?=$pData['height']?>px;
 <?
  $pData['liMarginX'] = $liData['width']-$pData['width'];
  $pData['liMarginY'] = $liData['height']-$pData['height'];
 ?>
 margin: <? echo pData['liMarginY']/2; ?>px <? echo pData['liMarginX']/2; ?>px;
}

What this allows us to do now is to change the size of ele­ments once at the top of the file and not recal­cu­late 12 mar­gin val­ues (24 if the mar­gin val­ues were asym­met­ric). Under­stand that I am not sug­gest­ing this will be used in every one of your projects going for­ward, but this kind of tech­nique has def­i­nite advan­tages over the stan­dard “sta­tic” CSS method.

Shrink that CSS

As men­tioned ear­lier, CSS can get pretty big. One thing that you can do to reduce CSS size is to auto­mat­i­cally gzip­ping your CSS files. To do this, you have two options on how to do so: straight from Apache using mod_​gzip /​ mod_​deflate or use PHP’s built-​​in com­pres­sion meth­ods, which we’ll do here.

Step One – Set Up The Gzip­ping Snippet

Inside of our CSS file, we already have a snip­pet of PHP that sets up the header:

<?php header("Content-type: text/css; charset: UTF-8"); ?>

All we have to do now, is add a sin­gle line of code set­ting an out­put buffer to use ob_​gzhandler before the header dec­la­ra­tion like so:

<?php
ob_start("ob_gzhandler");
header("Content-type: text/css; charset: UTF-8");
?>

It should be noted that there are other ways of doing gzip com­pres­sion and they all have their ben­e­fits and short­com­ings. My pre­ferred method is using mod_​deflate as men­tioned ear­lier, but not all design­ers and devel­op­ers have that option.

If($usingPHP==TRUE) { return ‘Happiness’; }

Adding pro­gram­ming logic to a style sheet lan­guage is noth­ing new. Many web­sites deter­mine what stylesheets they use based on URL, login sta­tus, or even the date. Here’s a sim­ple exam­ple that can be applied eas­ily to blogs and e-​​commerce sites (amongst oth­ers). Let’s assume that you have a h1 tag that is replaced using the Phark image replace­ment method described by the fol­low­ing CSS:

h1 {
 width: 300px;
 height: 80px;
 text-indent: -9999px;
 background: url(images/logo.png) no-repeat;
}

By adding a lit­tle PHP in the mix to deter­mine the date when the CSS is loaded, you can then spec­ify a dif­fer­ent image for a hol­i­day like Google often does with its Google Doo­dles (although they use a dif­fer­ent tech­nol­ogy solu­tion to do so):

<?php
 $month = date('m');
 $day = date('d');
 if($month=='12' && $day=='25') {
 	$logoSrc = 'images/holidayLogo.png';
 } else {
 	$logoSrc = 'images/logo.png';
 }
?>
h1 {
 width: 300px;
 height: 80px;
 text-indent: -9999px;
 background: url($logoSrc) no-repeat;
}
Normal Logo becomes Holiday Logo

This is just a super sim­ple exam­ple. Your CSS is just wait­ing to be amped up by PHP. What you do with it can vary from per­son to per­son. One of my per­sonal uses is to use it as a way of obscur­ing and embed­ding @font-face files using data URI strings and check­ing the ref­erer request­ing the file sim­i­lar to parts of the tech­nol­ogy that Type­kit uses:

<?php
// This function grabs the file and converts it to a URI string
function data_url($file, $mime) {
 $contents = file_get_contents($file);
 $base64 = base64_encode($contents);
 return ('data:' . $mime . ';base64,' . $base64);
}

$checkReferer = $_SERVER['HTTP_REFERER'];
$checkMatch = preg_match('/yourdomain\.com/',$checkReferer);
if($checkMatch) {
?>
 @font-face {
   font-family: FontName;
   src: local("FontName"), url(<?php echo data_url('FontFileName.otf','font/otf'); ?>) format("opentype");
 }
<?php
} else {
 /* This @font-face asset is unavailable */
}
?>

CSS Vari­able Controversy

Using vari­ables in CSS, no mat­ter the pros and cons has been a con­tro­ver­sial issue for years. Like I said at the begin­ning of this arti­cle, I am not going to argue for or against the con­cept of CSS Vari­ables or CSS Con­stants. Some very respected designer and devel­op­ers have argued against it, while oth­ers have argued for it. I hope, for the sake of a bet­ter web, that an effec­tive CSS-​​only solu­tion hap­pens sooner than later. In the mean­time, those of us who sup­port CSS vari­ables and con­stants can rely on our server-​​side lan­guages while those who do not sup­port them will sim­ply con­tinue on as normal.

What Ideas Can You Come up With?

I’m always on the look­out for new and inno­v­a­tive ways to super­charge my CSS with PHP. What are some of your favorite use-​​case sce­nar­ios for mix­ing CSS with PHP?


You must be logged in to post a comment.