Build a PHP Switcher

For your style-sheet-switching pleasure, A List Apart offers the
Switcher, a piece of
JavaScript that dynamically changes page styles. Functional as it is,
it quite unfortunately relies on the user to have both JavaScript and
cookies enabled. There’s not much we can do about the cookies, but we
can sidestep client-side processing with a little help from PHP.

Article Continues Below

PHP is a scripting language available on many, many servers. It’s
fast, it’s free, it’s open source and it handles everything on the
server side, so there’s no need to worry about users who have
disabled client-side scripting in their browsers. If you’re not sure
if your host has PHP installed, just ask them!

STAGE ONE: Setting styles#section2

The first step is to create a new file on your server named
switcher.php and paste the following code into it. (Line wraps are marked ». –Ed.)

<?php
setcookie ('sitestyle', $set, time()+31536000, »
 '/', 'yourdomain.com', '0');
header("Location: $HTTP_REFERER");
?>

When it’s queried, this file will write a cookie for the user
detailing which site style to use. The cookie is set to expire in one
year, and then the script sends the user back to the referring page.
All of this happens behind the scenes, so the user will never really
“see” switcher.php in action. To them, it looks simply as though
their page is refreshing. Don’t forget to put your own
“yourdomain.com” into the script, or your cookie won’t be valid.

Telling switcher.php which site style to use is an equally simple
matter. You can query it using conventional HREF links in text,
images, or even flash. All you need to do is write a link to
switcher.php and append a query string defining the style sheet you
want.


click here to change to RED style!

In the above case, “red” is the name of the style sheet you want to
use. There’s no need to append the .css file extension here; that
gets done later. The link calls up switcher.php and tells it to use
“red”, leaving the switcher to do the rest. As an alternative to HREF
links, you can use form elements to select and set your style sheets.
Try this drop-down menu:

<form acti method="post">

<input type="submit" value="Change Style">
</form>

STAGE TWO: Detecting styles#section3

It’s all very well and good to allow users to choose styles and have
cookies written for them, but without a cookie detection script, the
whole system falls on its face. So for every page of your site that
you want to use user-defined style sheets, paste this next piece of
code into the <head>.

<link rel="stylesheet" type="text/css" 
 media="screen" title="User 
Defined Style" href="<?php echo 
(!$sitestyle)?'defaultstyle':$sitestyle ?>.css" />

You’ll notice that this is a normal <link> element, the kind you’d
use to include any standard CSS file, but there’s an important
difference; where you’d normally write the name of your style sheet,
we’ve used:

<?php echo (!$sitestyle)?'defaultstyle':$sitestyle ?>

This tiny script detects which style is in the user’s cookies and
prints out the result. If the user doesn’t have cookies enabled, or
just hasn’t chosen a site style for themselves yet, the script will
default to “defaultstyle.css”. Feel free to change
“defaultstyle” to whatever your default CSS file is named.

So there you have it. A cross-browser, backwards-compatible,
forwards-compatible, standards-compliant style sheet switcher in just
five lines of code. It’s fast, straightforward, and universally
accessible because there’s no processing done on the client side. For
the Geckophile in you, you should also make reference to your
alternate style sheets within the document <head>:

<link rel="alternate stylesheet" 
   type="text/css" media="screen" 
   title="Fire Engine Red" href="./redstyle.css" />
<link rel="alternate stylesheet" 
   type="text/css" media="screen" 
   title="Grape" href="./purple.css" />
<link rel="alternate stylesheet" 
   type="text/css" media="screen" 
   title="Scary" href="./blackout.css" />

Though not necessary, listing your alternate style sheets in this way
enables users of the Gecko browsers (Netscape 6+, Mozilla 1+) to
change style sheets from within the browser interface. All they need
to do is go to View > Use Stylesheet and pick which one they’d like
to use.

That’s it. Get out there and style!

About the Author

Chris Clark

Chris Clark is a confirmed HTMinimalist who likes long walks, CSS and standards compliance. When he’s not fretting about download times or his WAI rating, he’s tinkering with his online playground at decaffeinated.org.

87 Reader Comments

  1. Whoops – typo in post. The switch does not work.

    /* Stylesheet 2 */
    /* —————————————————– */
    span.metric { display: none; }
    span.imp { display: inline; }

  2. Made a workaround using with internal attributeNodes for metric and imperial values, and a script to change the childNode accordingly.

    Not quite as good as if it were totally driven by CSS, but at least it works in the DOM compliant browsers – and non-compliants just get stuck with the default metric, so it’s not all bad.

  3. I have something just like this, using sessions and PHP, but I also have control-blocks scattered at intervals in the source-framework to do special modifies at special designs, not just CSS.

    Try switching from one design to another, and view source for all of them; they’re kinda the same, but also not quite, depending on the design. The writing of these extra style-HTML is very easy, and stored away in separate files and functions.

    But it sure will take a lot out of your servers resources when many come alookin’, though. Beware.

    Alex

  4. I’ve tried to use the PHP Styleswitcher, but it doesn’t seem to work. I’m a PHP novice, but worked through the example and tried it. The URL is http://www.themmgroup.com/example.php

    I checked the source of the executed PHP file and it says:

    Warning: Undefined variable: sitestyle in d:websitesvirtualwebsthemmgroup.comexample.php on line 7

    Dunno what I’m doing wrong! My ISP is using PHP Version 4.0.4pl1. Is this a problem?

    Thanks

  5. Richard some configurations will choke on this line

    ?php echo (!$sitestyle)?’defaultstyle’:$sitestyle ?>.

    if $sitestyle is not set at all. Try switching the line to this.

  6. In reply to the poster Natcher00 about not validating due to the & in the PHPSESSID, simply add the following to yopur .htaccess file:


    php_value arg_separator.output “&”

    Now PHPSESSID is appended with & and not &

    Pete 🙂

  7. The problem with using php in a css file is that you lose the benefit of the client’s browser caching the css file after a single access. Now that the css file is dynamic, the browser will have to download it again each time a page is viewed. So you may want to keep your core css in a static cacheable .css file and the few scripted parts in a small .css.php file. This saves bandwidth for everyone, woo!

  8. I would’ve jumped in earlier, except that I don’t read here very often. My bad.

    I’ve had a tutorial up on PHP + skinning for over a year here: http://www.domesticat.net/skins/howto.php

    It’s interesting to see that other people are interested in this particular bandwagon.

    One thing that I did differently than everyone here, it seems, is make each skin’s name numeric. (I currently have seventeen.) Keeping the names numeric means that I can run a very specific set of checks on the requested value of $skin (is it a positive integer? is it within the range of numbers I specify?) and drop the user back to a default skin if their requested value of $skin is invalid.

    In some ways what I’m doing goes a bit beyond the scope of this discussion; I’m using the value of $skin to do more than just swap a stylesheet. There are a lot of extras available on my site that are just a bit too much for those using modems, lynx, or handhelds, so there are superslim versions of the site geared toward those devices.

    Most of the tutorial has more to do with preparing your site for skinning purposes, and most of it’s utter common sense. Perhaps it’ll help someone in the future.

  9. Great article!

    I tried it out and got it to work after a short while. The only problem is: the cookie doesn’t get written in NN4 and so the whole switching thing fails in that particular browser.

    Does anyone have a clue why? I’d love to hear it 🙂

    Cheers Martin

  10. I know this forum has been dead for a while but hopefully one of you PHP heads is still checking it out. I use an SSI tag to include a navbar, and I was able to do that in my index.php file using a php include statement. (because apparently regular SSI tags won;t work here). THe problem is, none of the css styles get applied to the included navbar, which I tried as an html, a php, and I even tried adding the stylesheet select code that goes in every page to no avail. I hope someone can help; I’m not sure how to fix this.

  11. ok disregard the previous post, I figured it out. It may have been a simple thing to most but when you simply don’t know PHP other than what you copy and paste…..

    At any rate I’m having a smaller yet similar problem. I used the following to include my nav.php –

    And then in the nav.php we have

    Home | “);
    echo (“Sights | “);
    echo (“Sounds | “);
    ?>

    The CSS switcher DOES affect these links as they appear on index.php through a browser, but the applied CSS style does NOT affect the pipes (|) that are in between the links here. I know it seems trivial, but not only do I want the pipes to appear correct, eventually I may add more to the nav bar, like a table to hold the links, or other non-link text. Please help

  12. I noticed that without cookies enabled this whole thing fails to work. I guess this was obvious but I had originally thought that setting the cookie was simply so that the user came back to his or her chosen style. Is there a workaround that allows the switcher to still work if cookies are disabled or is that just how it is?

  13. Yes, look at previous posts.

    There were a lot of suggestions and samples to achieve this using SESSIONS. Haven’t looked into it myself but will certainly do as I get more into PHP.

    Cheers Martin

  14. I *HAD* it all working on my blog (MT on Apache2/PHP4.3.0) and after one day and a couple of index-rebuilds it was all gone… 😕 The switcher.php wasn’t working (anymore): the browser kept on that page and didn’t return to index.php with a new stylesheet.
    Now I see a lot of suggestions here but I miss a complete solution e.g. not just rewrites of some possible buggy rule in switcher.php 🙂
    Anyone PLEASE? TIA!

  15. I wish that there was a way of doing this using ASP. I know, I know, PHP is better, faster, etc. The problem is, my ISP doesn’t have PHP installed, and only supports ASP. The website I’m working on (see URL) is entirely authored in standards-compliant xhtml and css, and I just wish I could take advantage of that.

  16. But I’d imagine it was possible, no?

    I did it with ColdFusion myself. Yes, a few minutes of downtime at work.

  17. but using sessions, it wont save the users theme will it? cause each time they go the site, they will view the default theme, wont they?

  18. If this works, and I guess it does, then why doesn’t AListApart use this in addition to the Javascript solution. If they used this as well (instead of an empty response on the buttons) then Opera users could switch styles as well…

  19. i tried this a short while ago, and it didn’t work for me in netscape. to get around it i tried adding AddType application/x-httpd-php .css to .htaccess, and keeping the .css extension, which for some reason also didn’t work in netscape, although IE was fine (never tested opera). never did find out why =.

  20. I’m using this on my blog website http://www.slowchildrenatplay.org/ and it works fine in IE 5.5, IE 6 and Netscape 6.2. When I try to change the styles in Netscape 7 though, I have some trouble. When I click one of the style-changing links, the browsers goes to http://www.slowchildrenatplay.org/switcher.php?set=style but doesn’t refresh… it stays there, looking blank. If I hit the back button and refresh the index page, the new style is applied. Does anyone know how this switcher works with NN 7? Can someone look at my code and see if I made a mistake? (I’ve double checked a few times, and everything appears to be in order.)

  21. If you use $SERVER_NAME instead of ‘yourdomain.com’ then you don’t have to type in your domain name and virtual hosts, will all work…

    Also I do my switching like so:-

    if have a directory with css files in (amongst other things…)
    so include the following from a php library file:

    function getCssFiles($dirPath)
    {
    if ($handle = opendir($dirPath))
    {
    while (false !== ($file = readdir($handle)))
    if ($file != “.” && $file != “..” && substr($file,-4) == ‘.css’)
    $filesArr[] = trim( substr($file,0,strlen($file)-4) );
    closedir($handle);
    }
    return $filesArr;
    }

    //load the css file names into an array
    $CSS = getCssFiles($CONFIG[“HomeDir”].”inc/”);

    then when i want to include the css file name
    $template is a variable pulled from a cookie or query…

    $key = array_search($template,$CSS,true);
    if ($key !== FALSE) { $usethis = $template;
    else { $usethis = ‘default’; }

    so there you go…

    its all automatic, no list/array maintainence. You can add/remove css on the fly. and it has secuity to stop dodgy inputs, if the css is not on the list, your not coming in 🙂

    btw, nice work ALA i like what your doing!

    [Hilarious joke, envolving future thinking, to inspire the world and keep the web ‘live’ :]

  22. Thank you for putting up a complete example for a novice like me! i spent 12 hours straight playing with this idea and it wasnt till i used your example that i got everything to work beautifully! THANX!

  23. I’m trying to use the code on the first page of this forum dicsussion but it doesn’t work. It doesn’t change the css, jsut stays with the default one.

    The server has register_globals on, but enable trans_id is enabled. It’s php 4.3.2. Could this be the problem?

  24. sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss

  25. Hi there, I’m trying to use this code to switch styles on my website. I have used ALA’s Javascript switcher before, and it worked. But I can’t get the PHP version to work! I followed the tutorial step by step, and checked everything I could. It just shows plain text without any stylesheet (even if I let it show the default one). My server runs PHP and other scripts work perfectly.

    Can anyone please help me? Greetings from the Netherlands,

    Nick

  26. I tried to implement the code given by Peter Hawkes and all works fine after the first click… the first time visiting the page, I get:

    Notice: Undefined index: csschanger in c:hostingwebhost4lifememberbraincreseannewindex.php on line 32

    anyone know why?

  27. I am using the switcher by peter hawkes:

    here is more chance that a user will have cookies disabled than JavaScript disabled. All the above will not work without cookies.
    I am using SESSIONS in my version, this script assumes that PHP 4.2+ is installed and that register_globals is off with –enable-trans-sid.

    Code as below:


    ‘;
    $_SESSION[‘csschanger’]=$stylesheet;
    break;
    case ‘css2’:
    $stylesheet = ‘‘;
    $_SESSION[‘csschanger’]=$stylesheet;
    break;
    case ‘css3’:
    $stylesheet = ‘‘;
    $_SESSION[‘csschanger’]=$stylesheet;
    break;
    case ‘css4’:
    $stylesheet = ‘‘;
    $_SESSION[‘csschanger’]=$stylesheet;
    break;
    default:
    $stylesheet = ‘‘;
    $_SESSION[‘csschanger’]=$stylesheet;
    }
    }
    ?>



    CSS Changer

    ‘ ;?>


    ?css=css1″>Stylesheet 1

    ?css=css2″>Stylesheet 2

    ?css=css3″>Stylesheet 3

    ?css=css4″>Stylesheet 4


    BUT.. Is there a way of doing it so it validates??

    I have put this code as one file and used then included it each page.. can i change the style changer links to something like :
    at the end… THIS DOESN’T SEEM TO WORK FOR ME.

  28. Have just found out you can hide the session ID by putting

    ini_set(“session.use_trans_sid”, 1);

    in your switcher code

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career