Cascading Style Sheets are an amazing tool, having transformed Web Design as an industry and the Web as a communications medium. But in all of its glory (and it is glorious), CSS has some flaws. The most frustrating for me is its static nature. I want to be able to reuse values (CSS variables if you will), I want to make use of browser detection instead of CSS hacks, or IE’s proprietary conditional comments and I want to use logic to serve up specific rules in certain situations. Enter PHP (or your server-side langugage of choice), which will provide us a wealth of new options for working with our CSS, including the ability to adapt to our end-users’ needs.
Hello…. JavaScript Can Do That Already!
Yeah, client-side scripting can handle most of these requirements, but I don’t want to rely on a technology for my presentation that can be disabled by the user or their corporate IT department and frankly the JS support of mobile devices is poor at best. Enter server-side languages, which cover all of these bases without impacting the program or device rendering the site.
What I’ll Cover
- The Initial Setup
- Serving a Dynamic (PHP) File as CSS
- Useful Variables and Practices
- Implementing Browser Detection to Avoid CSS Hacks
- Putting it All Together
- Too Much Considered Harmful
- Acknowledgments and Sources
- Your Turn
The Setup
This article assumes that you have a Web server at your disposal that is running one of the aforementioned scripting languages and that you have a basic understanding of scripting in that language and know a bit about CSS. For the purpose of this write up I’ll be using PHP, but I have implemented versions of this system on production sites running JSP, and there’s no reason the same couldn’t be done with Ruby on Rails, Python, ASP or any other server-side solution.
This system can be as detailed or relaxed as you’d like, so I’m going to keep this write-up relatively simple with a few interesting bits thrown in. If it proves to be an interesting subject I’ll write a follow-up showing advanced usage. Let’s hit it!
Serving a Dynamic (PHP) File as CSS
In your editor of choice create a new PHP file. I’m calling mine styles.php. Paste this line at the very top of the document:
<?php header('Content-type: text/css'); ?>
This tells the server that the page should be sent to the browser as a CSS document, so the file won’t need the .css
extension. All of our work will be done in this bad boy. So, on to the next step.
Useful Variables and Practices
So, we have a PHP file that has a serious personality disorder, thinking that it’s a style sheet. What the hell are we going to do with it? Well, we’re going to set a few key variables that will make life much easier. Specifically, we’ll set variables for common measurements (columns, containers and the space between) and some colors from the site’s palette:
$gutter = '10px'; /* Used to separate visual blocks */
$pageWidth = '1000px'; /* Width of the Web page */
$pageWidthPadded = '980px'; /* $pageWidth minus padding ($gutter x 2) */
$col1 = '800px'; /* Width of the main content area */
$col1Padded = '780px'; /* $col1 minus padding ($gutter x 2) */
$col2 = '180px'; /* Width of the sidebar area */
$col2Padded = '160px'; /* $col2 minus padding ($gutter x 2) */
$lightGray = '#e5e5e5';
$charcoal = '#464646';
$orange = '#f60';
$darkBlue = '#0059b2';
The width variables will prove useful in creating a site as they guarantee consistent presentation from page to page and template to template. This model can easily be extended for multiple column widths, so if you want to subdivide Column 1, you only have to set it up once, creating the variables ($col1A
, $col1B
etc.) and setting their values to the appropriate widths. For you folks who love them grids, this should make life pretty easy.
Setting up color variables simplifies the initial site build-out and future revisions. When you return to the style sheet six months from now, you’ll notice $darkBlue
is much easier to remember than #0059b2
.
So, now that we have width and colors, it’s simple to use these new variables in the style sheet, all you need to do is use PHP’s echo shortcut (<?= 'print this' ?>
):
#Wrapper {
background-color: <?= $lightGray ?>;
border 1px dotted <?= $darkBlue ?>;
margin: <?= $gutter ?>;
width: <?= $pageWidth ?>;
}
Advanced: I’ve begun to separate the measurement value (px, em, pt) from the actual numerical value so I can harness the power of PHP to do my math for me. That’ll be the subject of a future write-up.
Implementing Browser Detection to Avoid CSS Hacks
I’ve used a couple of different packages in the past; at the moment I use BrowsCap, which covers these needs nicely, but use whatever fits your needs best. Place this code at the top of styles.php, after the PHP header line:
require_once('Browscap/Browscap.php');
// Create a new Browscap object (loads or creates the cache)
$bc = new Browscap('Browscap/cache/');
// Get information about the current browser's user agent
$current_browser = $bc->getBrowser(null,true);
$browser_platform = $current_browser['Platform'];
$browser_name = $current_browser['Browser'];
$browser_ver_major = $current_browser['MajorVer'];
$browser_ver_minor = $current_browser['MinorVer'];
$browser_ver_full = $current_browser['Version'];
$is_ie6 = false;
$is_ie7 = false;
$is_safari = false;
$is_ff = false;
if ($browser_name == 'IE' && $browser_ver_major == 6) {
$is_ie6 = true;
} elseif ($browser_name == 'IE' && $browser_ver_major == 7) {
$is_ie7 = true;
} elseif ($browser_name == 'Firefox') {
$is_ff = true;
} elseif ($browser_name == 'Safari') {
$is_safari = true;
}
So we now have a few variables that will allow us to quickly determine whether the user’s browser is IE 6, IE 7, Firefox (any version) or Safari (any version). You can extend this model to fit your specific audience and needs.
Putting it All Together
Sweet, now we can rock the styles all dynamic-like! Here are a couple of examples for you to nibble on:
body {
<? if($browser_platform == 'MacOSX') { ?>
font: .85em/1.4 normal "Lucida Grande", Verdana, sans-serif;
<? } else { ?>
font: .75em/1.4 normal "Lucida Grande", Verdana, sans-serif;
<? } ?>
That block outputs a larger font size for folks who are on a Mac compared to folks on PCs or other devices.
The next one modifies the value of a top margin, serving up 5px for IE 6, and zero for all other browsers.
#NavWrapper1 {
display: block;
height: 18px;
<? if ($is_ie6) { ?>
margin-top: 0;
<? } else { ?>
margin-top: 5px;
<? } ?>
margin: <?= $gutter ?>;
width: <?= $pageWidthPadded ?>;
}
Advanced: This method can be used to detect alternate browsers as well. So, you could detect a mobile browser and serve up a separate style sheet. Or if you detect a screen reader you could serve up a style sheet with proper aural rules defined.
That’s it, we’re rolling with dynamic CSS, harnessing the power of both PHP and Cascading Style Sheets. There is a lot more that can be done, but I hope this opened a few avenues for experimentation on your future projects.
In Moderation: Too Much Considered Harmful
It would be really easy to overuse this method. Do not try to replace proper use of grouping and the cascade with PHP. You won’t gain anything but frustration and larger style sheets. Take the time to think through the variables that you are going to create to make sure they make sense and are not simply recreating existing CSS functionality.
Acknowledgments
I am by no means the only person to think of this, there are many others who have covered the topic on their sites, but I felt that there were a few components missing, so here we are. I hope I added to your toolbox. It is also very important to note that there are some great folks with whom I’ve worked who have expanded on the concept and helped me flesh it out to be a viable and reusable tool in the Real World ™, most notably the inestimable Leesa of Red Velvet Cafe.
Your Turn
I look forward to your feedback and questions, so please leave a comment.
[…] […]