I recently spent an extortionate amount of time adding a site preferences panel to my site design. It's a solution composed of many parts, put together piece-by-piece with the knowledge and assistance of several Netizens. It is by no means perfect and certainly not indispensable—but it sure put my tinkering skills to the test. It surprises me how obscure information about adding site preferences is; Google searches on the subject have a high signal-to-noise ratio, and a couple of e-mail enquires to webmasters went unanswered. In keeping with my blog's tagline, here is the "stuff worth sharing". But mostly, as usual, I document the process mainly so I can remember how it was put together!
The site preference panel as been remade. Details here.
Requirements
- The panel should be hidden by default;
- It should offer a way to read with musical accompaniment;
- It should allow CSS to be disabled (e.g. for small screen viewing);
- It should allow stylesheet switching, and be resize-able;
- It should allow the user to change font size;
- It should be constructed and laid out using valid XHTML and CSS;
- It should work (well enough) in Safari, Firefox, Internet Explorer 6+.
Toggle the panel on/off
I wanted to create the effect of the prefs panel sliding out from under the navigation menu in the header. Likewise, it should slide up into the menu when the panel is closed. The K2 theme for WordPress already includes a (partial) script.aculo.us JavaScript effects library. Kristin Pishdadi blogged her method of utilizing this to toggle site navigation items, and adapting the same trick to display site preferences seemed like a logical development.
Instead of a text link for the toggle, I used a graphical "switch" positioned within the header. Originally this had no label and (according to feedback in the WordPress Forum) could be overlooked. To address this valid criticism I added a text label to make the function a little more transparent. The code for the switch, within div id="header", is:
<p id="prefs">
<a href="#" onclick="Effect.Combo('sitepref', {duration: .5}); return false" title="Click to show/hide site preferences">
<img src="<?php bloginfo('template_directory'); ?>/sitepref2.gif" width="52" height="28" alt="prefs" />
</a>
</p>
Positioning is done with the following CSS:
#prefs {
position: absolute;
float: right;
left: 100%; /* needed for safari + firefox */
top: 130px;
margin-left: -80px;
z-index: 1000000000;
}
Note that the switch won't display the panel unless JavaScript is enabled (as it nearly always is). Which is a good thing, since switching styles and changing font size won't work if JavaScript is disabled anyway.
Now to place that panel. This is added to header.php just below div id="header" (which contains ul class="menu") like this:
<div id="sitepref" style="display: none;">
</div><!-- Close div sitepref -->
Note that the div has an inline style set to hide the div by default. We get to style the div for display below.
Soundtrack options
Oh, you're still reading? I like listening to music but I can't make any, and don't want repetitive embedded audio files terrorizing my readers (I hope there's more than one!). What we need is streaming radio—so how do we deliver it? My solution was to offer a pick-list of several Internet radio stations using various formats, in the hope that a given reader will have a client already installed that will playback at least one. It's perhaps a stretch to call this an "integrated" solution—but I use it to bookmark my favourite stations without the need to know in advance which client to launch. On my system I simply choose the station I want to hear and the appropriate client launches and begins streaming in the background, while I continue surfing.

The station selector is added within div id="sitepref" thus:
<div id="prefsnd" class="column">
<h3>SOUNDTRACK</h3>
<img src="../control_play.png" alt="snd" />
<p>Internet radio tuner:</p>
<form id="radio" action="http://www.bioneural.net">
<div>
<select class="inputbox" onchange="window.location=this.value;" name="list">
<option value="selected">Select station...</option>
<option value="stream url goes here">Station name</option>
</select>
</div>
</form>
<p>
Client: <a href="http://www.whatever.com/">Player</a><br />
Client may require configuration
</p>
</div>
Turn off CSS
Note to self: find an evening class to learn PHP! Disabling CSS sounds so simple, but getting this to work proved to be a challenge. When it comes to PHP and JavaScript my knowledge is pretty-much cut-and-paste.
In truth I'm not sure how important this functionality is in the Real World, but here in the Matrix "getting naked" and exposing your (hopefully) semantic markup is unadulterated nerdiness. There's nothing (much) erotic about looking at a site with no CSS on, but it can be a pleasure to get "back to basics" and relive the early style-constrained days of the web. Ah yes, the browser-default serif font and general lack of excitement that turns beautiful Safari into a Mosaic clone...

I looked into two ways to toggle CSS off and on, one "styleswitcher" based around JavaScript and the other around PHP. I actually tried several variations of each, but the choice essentially came down to two:
JavaScript styleswitcher
The ALA styleswitcher.js by Paul Sowden is pretty well-known. As well as a link to the appropriate JavaScript an empty href is required in the header:
<!--Start styles-->
<link rel="stylesheet" type="text/css" href="main.css" title="default" />
<link rel="alternate stylesheet" type="text/css" title="fluid" href="fluid.css" />
<link rel="alternate stylesheet" type="text/css" title="none" href="" />
<!--End styles-->
The actual switch is built like this:
<a href="#" onclick="setActiveStyleSheet('none');return false;" title="turn off">Off</a>
| <a href="#" onclick="setActiveStyleSheet('default');return false;" title="turn on">On</a>
The above is simplified; I got unexpected styling results, presumably because of the way K2 separates the default from the user-defined styles. You may fair better. Because styleswitcher.js sets a cookie, the CSS state will persist from page-to-page.
PHP styleswitcher
I found Chris Clark's PHP Switcher difficult to adapt. Although it can be repurposed for WordPress templates I wanted some simple code I could understand and that would keep my template intelligible. And Joe Skidmore provided it. With help from Joe and Marcus Crestani (who also wrote a PHP switcher) I could add a simple CSS toggle thus:
<!--Start styles-->
<?php ini_set('arg_separator.output','&amp;'); ?>
<?php if( $_GET['css'] != 'false' ) { ?>
<link rel="stylesheet" type="text/css" href="main.css" />
<?php if (get_option('k2scheme') != '') { ?>
<link rel="stylesheet" type="text/css" href="extra.css" />
<?php } ?>
<link rel="alternate stylesheet" type="text/css" title="fluid" href="fluid.css" />
<?php } ?>
<!--End styles-->
The first line encodes the ampersand that would otherwise generate a XHTML validation error (see here).
The second and last line of PHP enclose all the stylesheets and form the basis of the toggle (the middle bit is K2-specific). If css=false then nothing will be included between the comments; if css=true you'll get the lot. The actual switch is built like this:
<a href="?css=false">Off</a> | <a href="?css=true">On</a>
Despite some much-appreciated help, I wasn't able to get the CSS on/off state to persist using a session variable or cookie, in a way that suited my header.php template and its multiple stylesheet links. The solution? Decide persistence doesn't pay.
Alternative styles
You already know how this works—it's styleswitcher.js again! I wrote some rules in fluid.css to break the design out of its fixed-width container, allowing it to re-size according to the width of the browser window, with the primary content stacked on top of the sidebar.
<a href="#" onclick="setActiveStyleSheet('fluid'); return false;">Fluid</a>
| <a href="#" onclick="setActiveStyleSheet(''); return false;">Fixed</a>

What about swapping WordPress themes on the fly? Get this plug-in.
Changing font size
Some sites allow the user to specify an exact font size, or even typeface. I wanted a basic "size up" and "size down" control, and found a JavaScript solution here.

It's easy to implement, seems to work across the main browsers, and avoids having to have multiple additional stylesheets for each font size.
Resize-able three-column CSS layout
Having ditched the temporary table, I joined Matthew Levine in his quest for the Holy Grail, and decided to layout the prefs panel as a mini page (with header, 3 columns, and footer) inside a page. It may take some trial-and-error, and a calculator is optional, but the result is something like this (colours changed to highlight divs; the middle div is fluid-width):

The footer contains only an image, with the div height set to the height of the image:
#pfooter {
height: 10px;
background: #f2f2f2 url(spike.png) bottom center repeat-x;
}
For the record, here is the markup for the siteprefs div less the actual controls/ toggles:
<div id="sitepref" style="display: none;">
<div id="pheader">bioneural.net site preferences</div>
<div id="pcontainer">
<div id="prefcss" class="column">
<h3>STYLING</h3>
etc.
</div>
<div id="prefsnd" class="column">
<h3>SOUNDTRACK</h3>
etc.
</div>
<div id="preffnt" class="column">
<h3>READABILITY</h3>
etc.
</div>
<div id="pfooter-wrapper">
<div id="pfooter"></div>
</div>
</div><!-- Close div sitepref -->
The CSS is slightly modified from this ALA example file.
Wow. What an Odyssey! I ask only, am I at the beginning or the end?









Holy crap, that's really cool, Bruce! I love how the form drops down very smoothly. Smells like ajax to me. ;-)
One recommendation for your radio stations: Indie Pop Rocks.
Thanks Rob,
You asked, you get! I've added it, after a moments pause to mull over what kind of anti-generic schizophrenic mix "Indie Pop Rocks!" might be...
Congratulations, by-the-way, on your engagement. I wish you happiness :-)
P.S. No Ajax, just the Prototype and script.aculo.us JavaScript libraries (which can be incorporated into static pages), and none of those XMLHttpRequest calls so essential to "Ajaxiness". I'm also (still) a little confused about what Ajax is and isn't (ditto the DOM); some folk seem to link it with anything vaguely interactive or animated.
Hi this prefs thing looks good, except in Opera. I havea seen a few such things like this. They all have the same issue in Opera.
I will be having a more indepth look at the tutorial in the near future
But just wanted to ask if you were aware of the opera issue; if you care? and if you have any ideas
looking 4ward to reading and playing with it - S
Hi Sam. Yes, an Opera user has pointed that out to me. I did even download Opera to see for myself. My previous site had fixes for IE and Opera; I've only recently added fixes for IE6 and below since 1/3rd of my visitors are using IE (incidentally, the IE fixes make use of the !important declaration, as suggested by Jasper here).
At present Opera users (all versions) make up just 1% of my visitors. Before I can justify spending time bending web standards to that browser's quirks, Opera would need to get a bit more popular. I'm not knocking Opera... but the prefs panel is a non-essential part of the site Opera users can do without. I seem to recall Opera had problems with K2's Ajax commenting too.
Hi Bruce,
Sorry about all of that stuff but I really didn't mean to 'steal' it. I just wanted it to be easy. I've updated the page and put a pretty little message at the top about your site and tutorial. check it out.
Hey, the site prefs thing is seriously COOL! I'm going to put it on my site this weekend. Do check it out next week. I'll fully credit you in the About this Site page (www.newtheatre.org.uk/site.php). However, if you're unhappy about any of it, do get in touch with me. May I use your Site Pref switch please? I'm rubbish at Photoshop!
Cheers,
Ali Blackwell
Go ahead Ali; the "howto" is online for the purpose of sharing. I do encourage modification so it's not a straight copy, but you're free to use the switch icon (which I modified from the Apple Developer kit anyway).