Cascading Style Sheets is a presentational
style sheet language. In that sense, it does not have a lot of the
functionality that many developers want to satisfy their programmer
instincts. Today, we're going to go over how to supercharge your CSS.
Tutorial Details
Introduction
Using CSS to power up a website is a requisite in the contemporary
web for non-Flash websites – and for good reason. CSS is powerful. It
can make or break a website (although usually IE6 is doing the
breaking). Even with its usefulness, designers and developers alike
have have wished for more out of the language since its inception over
twelve years ago with the CSS Level 1 Recommendation. Today, we’re
going to review some ways to Supercharge Your CSS With PHP Under The Hood.
Setting Things Up
Before the supercharging begins, we have to ensure that you have the
proper requirements for doing so. We are going to go over two methods
of making your CSS work with PHP, one that is short and sweet, and one
that is a bit more elegant and less noticeable to the user. Both of
these have the same basic requirement of a server running PHP. The more
elegant version requires a bit more:
- Apache (running PHP, obviously)
- An editable .htaccess file
Setting Up the Simple Method
Web browsers are not that picky about file extensions when dealing
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 interpret the result just like standard CSS. To do
so, add the PHP header that tells Apache to output the file as CSS:
- <?php header("Content-type: text/css; charset: UTF-8"); ?>
<?php header("Content-type: text/css; charset: UTF-8"); ?>
Then, just link to the PHP file like you normally would:
- <link rel="stylesheet" href="css/supercharged.php" media="screen">
<link rel="stylesheet" href="css/supercharged.php" media="screen">
Now that you have done this, you can–in theory–skip to the next
section of the tutorial dealing with CSS variables and constants, if
you would like; however, anyone who views your source is going to see
that you have a PHP file where a CSS file should be. Additionally, just
because the browser will interpret the result properly does not mean
that it will necessarily do other things like caching the file in the
browser. To fix this, we move on to the slightly more elegant version.
Setting Up the Elegant Method
Apache comes with a large number of .htaccess tricks. This is one of
them. We are going to tell Apache to interpret all CSS files in a
certain folder as PHP files, and the web browser (and your users) will,
generally speaking, not know that you are doing so. First thing to do
is to put the header data in your CSS file, just like the Simple Method:
- <?php header("Content-type: text/css; charset: UTF-8"); ?>
<?php header("Content-type: text/css; charset: UTF-8"); ?>
Then, instead of saving 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 example,
~/css/). Once you have done this, create a *.htaccess file in that
folder and add the following:
AddHandler application/x-httpd-php .css
This snippet tells Apache to interpret all CSS files in the folder
with the *.htaccess file with the PHP script handler. If you do not
have the ability to add this to a single folder or if you need this to
be serverwide, you can also add this to the httpd.conf server configuration file for Apache. To do so, you would want to add the previous snippet right below the group of AddType and AddHandler declarations (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
AddType application/x-httpd-php .php .php3 .php4 .php5
AddType application/x-httpd-php-source .phps
AddHandler cgi-script .cgi .pl
Just remember that if you do add this to your httpd.conf server configuration file that EVERY
*.css file on the server now must have the PHP header for text/css
prepended to it. This is why my recommendation is to add it via
.htaccess
Start the Engine with CSS VariablesThat is a lot of CSS. Why is this? A lot of times it is because the
CSS is being delivered uncompressed and not optimized. The more likely
suspect is CSS bloat and poorly maintained code. One popular option to
improving code maintainability is to implement CSS Variables through
PHP.
What this means is that instead of having CSS like this (yes, this
would produce an aberration of design, but it’s good at illustrating
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;
- }
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';
- ?>
- 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?>;
- }
<?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 variable names is for illustration
purposes only. Obviously, these variables can be as long as or as short
as you like, and shorter variables make for smaller file sizes.
In the example above, we have used basic variables to set up a
monochrome color scheme that could then be used throughout the website
in other styles. These variables could easily have been interchanged
with $color01, $color02, $color03, etc to produce similar effects.
Often, designers and front-end web developers get asked by clients
“Hey, can you make all of the text a little darker?” or “Can you make
all of the text just a little bigger?” While using variables like this
will not always be the best solution, it often would reduce the
maintenance time when using many templating systems and blogging
platforms (WordPress, Moveable Type, Expression Engine, etc) or
corporate CMSes (Drupal, Joomla, Bitrix, etc).
An alternative method of storing the variables is to store the data
in associate arrays (which is my preferred method), which produces 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']?>;
- }
<?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']?>;
}
Calculations in CSS
Once you have set things up for using PHP with your CSS, you can
then do some neat things like calculations. Let’s assume that you want
to set up a system in you provide a bunch of DIVs on screen, each with
a different type of element inside. Each element type (i.e. img, p,
blockquote, etc) has a unique height and width controlled via CSS, and
you want the amount of margin to be based off these values like so:
In this scenario, you want to set up a standardized grid that
contains three different types of elements (img, p, and blockquote)
encapsulated in two different containers (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 element types has a different height and width.
The positioning of the elements on the inside must be dead center. Over
time, the heights and widths of the different DIVs/LIs and elements
will likely need to be changed. You could manual enter the amount of
margin for each of the different elements and/or use extra class
information on the container DIVs to add the appropriate amount of
padding, but this is not that useful for quick changes, like those
wanted by someone who is prototyping in the browser or who has 200 of
these different elements for which they would have to modify data.
Step 1 – The Structure
First, we set up the XHTML content 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>
<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 Variable 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 standard sizes of the different
elements for use throughout 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'
- );
- ?>
<?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 Variables and PHP Calculations
Next, we continue the PHP file from Step 2 and utilize the variables
that we set in calculations. Additionally, we set the calculated
MarginX and MarginY values of the different elements to reduce the
number of calculations 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;
- }
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 elements once
at the top of the file and not recalculate 12 margin values (24 if the
margin values were asymmetric). Understand that I am not suggesting
this will be used in every one of your projects going forward, but this
kind of technique has definite advantages over the standard “static”
CSS method.
Shrink that CSS
As mentioned earlier, CSS can get pretty big. One thing that you can
do to reduce CSS size is to automatically gzipping your CSS files.
Step One – Set Up The Gzipping Snippet
Inside of our CSS file, we already have a snippet of PHP that sets up the header:
- <?php header("Content-type: text/css; charset: UTF-8"); ?>
<?php header("Content-type: text/css; charset: UTF-8"); ?>
All we have to do now, is add a single line of code setting an output buffer to use:
- <?php
- ob_start("ob_gzhandler");
- header("Content-type: text/css; charset: UTF-8");
- ?>
<?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
compression and they all have their benefits and shortcomings. My
preferred method is using mod_deflate as mentioned earlier, but not all
designers and developers have that option.
If($usingPHP==TRUE) { return ‘Happiness’; }
Adding programming logic to a style sheet language is nothing new.
Many websites determine what stylesheets they use based on URL, login
status, or even the date. Here’s a simple example that can be applied
easily to blogs and e-commerce sites (amongst others). Let’s assume
that you have a h1 tag that is replaced using the Phark image
replacement method described by the following CSS:
- h1 {
- width: 300px;
- height: 80px;
- text-indent: -9999px;
- background: url(images/logo.png) no-repeat;
- }
h1 {
width: 300px;
height: 80px;
text-indent: -9999px;
background: url(images/logo.png) no-repeat;
}
By adding a little PHP in the mix to determine the date when the CSS
is loaded, you can then specify a different image for a holiday like
Google often does with its Google Doodles (although they use a
different technology solution 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;
- }
|