A List Apart

Menu
Issue № 189

Invasion of the Body Switchers

by , Published in CSS, HTML, JavaScript, Accessibility, Interaction Design88 Comments

Since it was first released in 2001, Paul Sowden‘s Style Sheet Switcher has been downloaded and used by thousands of designers and developers and has spawned many client-side and server-side adaptations.

Having used Paul’s script on numerous projects, I began to wonder how style-sheet switching could be extended to give users even more choices or accessibility enhancements, so I turned to my good friend Brothercake to make my ideas a reality and Invasion of the Body Switchers was born.

Looking back at the original Style Sheet Switcher

Fantastically simple in its implementation, Paul’s original script was not without its woes.

Anchors which trigger the switching functions are generally present in the mark-up, which is a problem if javascript is unavailable, and the # anchors commonly used are an unnecessary annoyance.

<a href="#" onclick="return false;">Switcher</a>

The original solution also relied on multiple style sheets, using <link/> elements and “stylesheet” / “alternate stylesheet” semantics - this adds extra server calls, but more importantly, it does not allow for different media styles to be selected independently of each other.

Wouldn’t it be fantastic if we could do this without any physical mark-up, using a single Javascript and CSS file? Wouldn’t it be even more fantastic if we could target different media types independently, and give users a simple UI from which to select their preferences, all saved into a cookie until changed?

Well now we can, enter the Body Switcher.

The concept

Invasion of the Body Switchers is infinitely extensible, handling any number of options and media types, all from a single Javascript and CSS file. It works by adding one or more unique class names to the page’s <body> tag; styles are then defined using descendent selectors.

Our approach does require abandoning conventional “stylesheet” and “alternate style-sheet” semantics, but this doesn’t trouble me, because:

  1. Many browsers do not implement native style-sheet switching;
  2. Those that do, do not apply any persistence to a selected alternate stylesheet.

Making the menu

Before we start, let’s take a peek at the final result.

If you download the files now, you can refer to them as we can go through each component:

The XHTML

First include some empty switch containers, here I’ve used a <div> to contain the switcher:

<div id="screen-switcher"</div>

For each additional switcher you can add an extra container. For example, an additional switcher for print styles:

<div id="screen-switcher"></div>
<div id="print-switcher"></div>

Or even projection styles:

<div id="screen-switcher"></div>
<div id="print-switcher"</div>
<div id="projector-switcher"></div>

Switching tools are created into these containers only if scripting is available, leaving semantically neutral, empty containers when it’s not.

The script

Customisation of the script is very simple. First create a new switching form - defining the id of its container and the label text:

var screenSwitcher =
	new bodySwitcher(
	'screen-switcher',
	'Screen styles'
);

Then you can add any number of classes and their labels, to apply to this switcher control:

screenSwitcher.defineClass('default','Normal contrast');
screenSwitcher.defineClass('high','High contrast');

Adding new media types

To give a user the choice between different print styles without affecting screen presentation, add print options to the script.

var printSwitcher =
	new bodySwitcher(
		'print-switcher',
		'Print styles'
	);
printSwitcher.defineClass(
	'default','Default'
);
printSwitcher.defineClass(
	'small-sans','Small sans'
);
printSwitcher.defineClass(
	'large-serif','Large serif'
);

Additional media types can also be included, for example for hand-held or projection devices.

var projectionSwitcher =
	new bodySwitcher(
		'projection-switcher',
		'Projection styles'
	);
etc.var handheldSwitcher =
	new bodySwitcher(
		'handheld-switcher',
		'Handheld styles'
	);
etc.

The only restriction is that every class name must be unique, even across different media types.

The style sheet

A single style sheet can contain all the options and media types selectable by the user.
Any CSS rules may be applied to this style-sheet, simply by using descendent selectors from the additional <body> class names we talked about earlier.

Example screen styles

@media screen
{
	body {
		background : #fff;
		color : #666;
		}body.high {
		color : #000;
		}body.highvisibility {
		background : #000;
		color : #ff0;
	}
}

Example print styles

@media print
{
	body {
		font: 100% "Lucida Sans Unicode",verdana,sans-serif;
		}body.small-sans {
		font: 80% "Lucida Sans Unicode",verdana,sans-serif;
		}body.large-serif {
		font: 120% "Times New Roman",times,serif;
	}
}

Additional media styes can also be added as required.

@media projection {
	etc.
} @media handheld {
	etc.
}

Styling the switcher controls

The switcher controls are made from accessible, semantic mark-up and can be styled according to any site design.
Here is what the HTML looks like for each control; I’ll leave the styling up to you.

<form acti>
	<fieldset>
		<label for="select-screen-switcher">
		<span>Screen styles</span>
		<select id="select-screen-switcher">
		<option value="default">Normal contrast</option>
		<option value="high">High contrast</option>
		<option value="highvisibility">High visibility</option>
		</select>
		</label>
	</fieldset>
</form>

And that about wraps it up

That’s it! Take another look at the final result - a modern style sheet switcher which enables independent switching of different media types, and gives users much greater control over the output of your web pages.

This principle is infinitely extensible, so you could break it down further into individual preferences for fonts, colors, layout or orientation.

Except for the caveat

Invasion of the Body Switchers does not work (but is gracefully degraded) in Mac/IE5.

About the Authors

88 Reader Comments

Load Comments