Invasion of the Body Switchers

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.

Article Continues Below

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#section1

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#section2

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#section3

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#section4

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#section5

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#section6

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#section7

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#section8

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

Example print styles#section9

@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#section10

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#section11

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#section12

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

Andrew Clarke

Andrew Clarke is an art director and web designer at the UK website design studio Stuff and Nonsense. There he designs websites and applications for clients from around the world. Based in North Wales, Andrew’s also the author of two web design books, Transcending CSS and Hardboiled Web Design, and is well known for his many conference presentations and over 10 years of contributions to the web design industry. Jeffrey Zeldman once called him a “triple talented bastard.” If you know of Jeffrey, you’ll know how happy that made him.

88 Reader Comments

  1. There’s a typo/error right after “The concept”:

    Swtichers

    That aside, great to see another article on ALA, finally. Looking good 🙂 And it’s something I’m very likely to use. Kudos 🙂

  2. I can hear the click of keys as people across the internet type: “a-l-i-s-t-a-p-a-r-t.-c-o-m” 😉

    Great article to come up with.

    As for Ian Beatty “Safari problems” I am on the same rev of safari and I was able to see all the widgets fine.

    Not sure why you couldnt.

  3. Test page works perfectly in Safari 1.2.4 v.125.11 (my Safari version is exactly the same as yours and we naturally tested the demo before publishing it).

    You may be having caching problems — or you might have caught the server during a weird slowdown/hiccup in which a page element failed to load.

    Clearing your browser cache will demonstrate that the problem was in the cache; if another reader has the same experience using a different browser, it will prove the problem is on our server, and not in the code.

    In any case, the project works across browsers and platforms and we never, ever forget to check in Safari. 😀

    Ian Beatty wrote:

    >>Alas, Safari (1.2.4, v125.11) seems to have problems with the techniques. On the test page, the switcher widgets don’t appear at all. *Sigh*

  4. >>There’s a typo/error right after “The concept”:

    FIXED. Sorry. Thanks for catching it!

    >>I’m afraid there’s some quote curling where there shouldn’t be — in the first code snippet, for instance.

    FIXED. Sorry. Thanks for catching it!

  5. I can’t believe a new article showed up in my RSS reader! What a pleasant Friday surprise!

    Just digging into the article now, but it appears to be a fun concept that can allow for some pretty dynamic creations.

    Cheers for making my Friday afternoon!

  6. RE: Firefox…
    No problem with Firefox, those are @media=print and @media=projection styles. Unless you change the choice in the drop down and then print the page, you won’t see the difference.

    Welcome back ALA, it’s been a long time 🙂

  7. Nice work, really nice work.

    I’ve looked through the JavaScript and it looks good. However, there’s a memory leak in IE/Win.

    The problem is that inside the bodySwitcher constructor method an event handler is created. As it is created in the scope of the constructor, all fields of the object are in it’s scope. The handler is attached to the select node. This means the select node refers to the handler, refers to the object, which refers back to the select node. This circular reference cannot be cleaned by IE/Win.

    The problem can be solved by not keeping references to DOM nodes on the object and retrieving needed nodes using a getElementById call.

    See also http://jibbering.com/faq/faq_notes/closures.html#clMem

    As for the Safari problems, when working on sIFR I found that Safari sometimes needed to be forced to repaint. You can read more at http://neo.dzygn.com/archive/2004/09/forcing-safari-to-repaint You’ll have to make sure though that you won’t be using innerHTML when the script is used in a XML page.

    As for the script not functioning in IE/Mac, I found two possible reasons for this. One is that the onload event handlers don’t work in IE/Mac. The other is the space before the class name which seems to throw IE/Mac off.

  8. It’s always brilliantly simple things like this that make me wonder, “Now why didn’t I think of that?”

    I’ve had some problems with the other style switcher, so I’m hoping that this might work better.

  9. There’s an obvious accessibility use, but other than that, is there really any reason to allow the user to switch stylesheets on the fly like this. I mean, as long as we are compliant, shouldn’t the accessibility issues resolve themselves for the most part?

  10. Great to see ALA back. I was raiding the archives whilst there was nothing new being published and I found some good stuff for PHP. But a new article is even better.

    Just one thing about the code: instead of the more verbose
    if (typeof window.addEventListener != “undefined”)

    I’d opt for just
    if(!window.addEventListener)

    I thought ALA published on Tuesdays instead of Fridays. I much prefer Friday over Tuesday, because who doesn’t like Friday?

  11. My! Am I glad I couldn’t sleep tonite! (it’s 2:45 AM here in Paris).
    Yay! ALA is back!

    Yeah, I got nothing to say…

  12. Has possibilities as an accessibility feature or profile-site gimmick, but the biggest one for me is providing print-stylesheet hide/show options.

    For example, on a blog, you can have a print-stylesheet so that a user can print the article, but with this, you can have a simple checkbox at the bottom for whether they’d like to print the comments also, or just the original text. You could also provide a box for surpressing images.

  13. >Those that do, do not apply any persistence to a selected alternate stylesheet.

    Firefox can do it via the extension Stylesheet Chooser (or the “Plus” variation of the extension).
    And what about the Future ? I hope it will soon be implemented in browsers.

    The very big problem is that now it is absolutely not possible to switch style without JavaScript. Not a good solution for accessibility 🙁

  14. I like the trickery of what is shown in this article, although I personally like to opt for a server side solution since that gives a little less trouble with browser-side compatibility issues; if of course you have a server side solution at your disposal (like PHP or ASP). I take the trips to the server for granted.

    The thing that has been bothering me with all style selection methods that are not supported by the browser is when you offer a stylesheet that is targeted at a specific audience (the high contrast example); if someone cannot distinguish the selection boxes on the original page and needs the high contrast to see anything at all, how will that person be able to switch?

    I guess that the “alternative” stylesheet method that browsers like Firefox or Opera support are the preferred way for someone who needs a particular stylesheet in the first place, so should we use AND a body switcher type selection AND offer the ‘alternative stylsheets’ in the head of the document at the same time?
    (I realise this is beyond the scope of the article, but nonetheless)

  15. >> this doesn’t trouble me, because … many browsers do not implement native style-sheet switching

    But wouldn’t this take away the expected behavior of the browsers that do implement switching? The multiple stylesheets would not be switchable by the browser’s built-in switcher, and the user will have to use the controls on the webpage.

    Also, the fact that browsers don’t support different media is only a temporary problem that will eventually be fixed as the need arises – at least we have the semantics in place. By using this method as a quick-fix, won’t we be repeating the old-style web design mistakes of generating dirty code that breaks semantics and doesn’t really work as intended in every browser?

    Or am I missing something entirely?

  16. The reason for the traditional switcher not supporting multiple media types is that the semantics don’t have scope for it – we *don’t* have the semantics in place, and that’s why it was necessary to go outside them – abandon them, in fact – in order to acheive multi-media capability.

    Open to suggestions though 🙂 Just because we couldn’t think of another way, doesn’t mean there isn’t one.

    > if someone cannot distinguish
    > the selection boxes on the
    > original page and needs the high
    > contrast to see anything at all,
    > how will that person be able to switch?

    That’s an interesting point … maybe that implies that a separate, basic switching mechanism tied to the original semantics is still useful.

    > As for the script not functioning
    > in IE/Mac, I found two possible
    > reasons for this. One is that the
    > onload event handlers don’t work
    > in IE/Mac. The other is the space
    > before the class name which seems
    > to throw IE/Mac off.

    We used those event handlers specifically so that mac/ie5 wouldn’t attempt to run the script. If that’s changed, it still doesn’t work, because dynamically creating and populating a select element is fundamentally broken in mac/ie5 – it just creates a bunch of text nodes outside an empty selector. As far as I know there’s no way to fix that, so mac/ie5 is degraded to unsupported.

    > instead of the more verbose …
    > I’d opt for just …

    But scripts run faster if there are no strict-compilation errors – the shorter example would throw a strict warning 🙂

    > This circular reference cannot be
    > cleaned by IE/Win … the problem
    > can be solved by not keeping references
    > to DOM nodes on the object and retrieving
    > needed nodes using a getElementById call.

    Yeah I’m aware of this issue, but it’s a browser bug, and when it comes to changing your code to suit browser bugs .. well we all draw the line somewhere, and I draw it well before the point where I’ll re-structure my code so fundamentally.

    Personal choice, obviously. If the memory leak is a serious concern, this code tacked on the end of the script will clean it up:

    //add DOM cleaning function for win/ie
    if(typeof window.attachEvent != ‘undefined’)
    {
    window.attachEvent(‘onunload’, function()
    {
    //for each item in the document.all collection
    this.daLen = document.all.length;
    for(var i=0; i

  17. welcome back to the mix ALA!

    Nice article, at the present I use PHP switchers but will have to take another look at this as well….

  18. James, Andy: thanks for this great article and method. My only complaint is the interface. Many who use this method will only want to include the screen styles switcher on their site. Of the sites I can think of that use screen style switchers, nearly all of them use buttons, not dropdowns. How about some more interface options for those who don’t want ugly dropdowns on their site?

  19. Back in business…

    This article came with perfect timing, as I was just beginning to develop a style switcher for a project of mine. Many thanks for your efforts!

    Peace.

  20. Overall, a great article. Kudos!!!

    While the drop-down select controls are wrapped in wonderfully accessible labels, there’s still a problem. The technique of causing an action upon selection prevents the non-mouse user (blind person or motor-impaired visitor) from seeing the choices. The first down-arrow action selects and acts upon the first selection, usually unexpectedly and with surprising results. There’s a reason for those “go” buttons next to select controls.

  21. > The first down-arrow action selects
    > and acts upon the first selection

    It does, but you can also navigate a select element by pressing “ALT + arrow”, and then it opens the menu, allowing you to read all the choices without firing onchange until you press Enter.

    As far as I remember, the traditional reason for having a go button is that early browser implementations of javascript didn’t always support the onchange handler. Clearly it’s a problem if a selection is made when a user didn’t intend that, but browsers have a way of dealing with – and “ALT + arrow” is it – the keyboard equivalent of clicking to open the menu.

    Nonetheless, an alternative to select elements is certainly a good idea – it wouldn’t be too hard to modify the script to generate buttons or links … I’ll come back on that one 🙂

  22. Late to the party as usual 😉

    Cake seems to have covered the technical issues, so I’ll just add that I’m glad this has gone down quite well. Have fun with it.

    Andy Clarke

  23. Ok, whats there is great.

    However, being able to store the styles within different CSS files, and being able to load them all in on the fly from javascript would be awesome.

    Bloating the loaded CSS with all available combinations seems a bit excessive. The example is very small, but does not cater to sites that have a heavy use of CSS for layout.

    Also, putting “containers” into the markup would be better if it was able to be done on the fly. Keep markup clean.

    Adding a new skin to a site should be as simple as putting a new CSS file into a directory, and updating an array of available style sheets.

    I’m sure there are going to be browser limitations etc, but planning for the future with clean degredation for the past is always good :).

    Nice article.

  24. There’s gotta be a way to make the styles change for only a specified div on the page…

    (ex: a 2 column layout — how would you go about changing only the right column’s style?)

  25. There is a section “Server-Side” on ALA. As much as I’m thankful for this article, I’d like to see a style switcher that works server-side. No javascript and no cookies would be necessary. Although a server-side style switcher would be dependent on the capabilities of the server used, obviously.

    Maybe one should use document.write (not for xhtml) for the buttons or dropdowns, so only those who have javascript enabled can see the switching functionality. Maybe that makes sense, since only when javascript is enabled you can use the switcher. Or is this a bad idea?

  26. I also get the same problem as Bryan, in Mozilla Firefox 1.0 the contrast dropdown doesnt appear to change anything on the page, i also encountered the problem with opera 7.54.

    Good idea though i like it alot, if the firefox problem can be solved i would use it alot.

  27. > Bloating the loaded CSS with all
    > available combinations seems a bit
    > excessive.

    We wanted the whole thing to work from a single stylesheet, so that it reduces the complexity of implementing it. It also means that when changing styles, the change is instantaneous, as it was with the original switcher.

    But I can see what you mean – there could come a point of complexity where it would be too bulky to load all the styles at once. So putting aside a server-side solution [I’ll come back to that in a mo ..] how would you envisage it works? Say, the default stylesheet is loaded, then added to or replaced by the selection of new styles – essentially the same functionality, but new style sheets are requested on the fly instead of loaded in advance. Is that what you mean?

    > Also, putting “containers” into
    > the markup would be better if it
    > was able to be done on the fly.
    > Keep markup clean.

    Okay .. so where do created containers go? Where in the page are they appended? That’s the whole point of having a static container – so that the created elements have somewhere to go.

    > I’d like to see a style switcher
    > that works server-side. No javascript
    > and no cookies would be necessary.

    Well cookies would still be required, but yeah – a server-side alternative is a good idea, and will be forthcoming. I need a few weeks to write and test them thoroughly, but there are PHP and Classic ASP (JScript) versions on the way …

    > in Mozilla Firefox 1.0 the contrast
    > dropdown doesnt appear to change
    > anything on the page, i also encountered
    > the problem with opera 7.54.

    I’m not seeing any problems. Are you sure it’s not just too-subtle a visual effect in your particular setup? What if you select the hi-visibility layout – do you see that?

    Failing that, can you cite me platforms and build numbers for the browsers where you see a problem. Cheers 🙂

  28. While I feel this is the best client-side, I would like to reitterate what I would like out of this (any chance we can get a URL for updates to the project, if any will be made?)

    1. More UI options
    2. Break into multiple style sheets
    3. server-side version (lowest priority of the three)

    Still, I must say I do LOVE this method more than others I’ve seen. Not generating the Form elements if JavaScript is a very nice touch IMHO.

  29. > I’d like to see a style switcher
    > that works server-side. No javascript
    > and no cookies would be necessary.

    Personally, I believe that such a style-switcher should be fundamentally a client-side solution, but I know that Cake is working on a server side implementation. Me, I’m gonna stick with client-side. 😉

    >> Any chance we can get a URL for updates to the project, if any will be made?

    There WILL be updates, no doubt. And these will probably appear on either Cake’s site (http://www.brothercake.com) or/and my own (http://www.stuffandnonsense.co.uk). I will need to check with Jeffrey on the correct proceedures for updates to ALA articles. 🙂

  30. Probably a VERY stupid question, but is it possible to add some spacing and/or new linesin the code the JS creates? I’m kinda anal about things like being able to read generated code. My knowledge of JavaScript is no where near where I would like it to be, so I’m not sure if this is possible (honestly, I don’t see why many people would care for that, but I’m just weird that way).

  31. very nice to see ALA back on track!
    the contrast dropdown menu works correct for me in FireFox 1.0.
    When will the js-file be updated, or will you not add any correctings?

    peace

  32. >> Bloating the loaded CSS with all
    >> available combinations seems a bit
    >> excessive.
    > We wanted the whole thing to work from a
    > single stylesheet, so that it reduces the
    > complexity of implementing it. It also means
    > that when changing styles, the change is
    > instantaneous, as it was with the original
    > switcher.
    > But I can see what you mean – there could
    > come a point of complexity where it would be
    > too bulky to load all the styles at once. So
    > putting aside a server-side solution [I’ll
    > come back to that in a mo ..] how would you
    > envisage it works? Say, the default
    > stylesheet is loaded, then added to or
    > replaced by the selection of new styles –
    > essentially the same functionality, but new
    > style sheets are requested on the fly
    > instead of loaded in advance. Is that what
    > you mean?

    Just an overview 🙂 my opinions stem from me implementing CSS/tableless layouts to all the projects from my employer. Some CSS can get … semi huge (its hard to keep a grip on efficency in front end within a big team thats still learning (at least where i am now ;)).

    And yes, thats exactly what I mean 🙂 Load them in when needed. (I had an example of the javascript, if i remember its a bit browser specific but … bah, no idea where now :().

    CSS files should represent a look, or a style, or a base style for the site. It makes more sense to seperate them into multiple files so that a “feel” can be worked on in isolation, and you know that what you are working on will be less likely to effect any other styles.

    >> Also, putting “containers” into
    >> the markup would be better if it
    >> was able to be done on the fly.
    >> Keep markup clean.

    > Okay .. so where do created containers go?
    > Where in the page are they appended? That’s
    > the whole point of having a static container
    > – so that the created elements have
    > somewhere to go.

    Append them wherever you want. If you have a standard layout naming convention, append them inside your container where appropriate.

    There may well be a “controls” area within your layout that would be appropriate, but I dont think it that adding specific “body switcher” control divs should occur.

    Use the CSS to position/style it.

    Its really fine lines I guess. I like clean markup. I want my content accessible for browsers that do and do not support features.

    I like the idea of things being easily implemented, but things need to be extendable also. With front end development i try to use the same practices for big sites as I do with small. The workload is comparable, but it lets small sites grow to massive sites with less upgrade time.

    I have to finish this post, im at work 🙂

  33. nb, for things like increasing text size on a few key areas, i think what you have is perfect 🙂

    document.createStyleSheet for IE or adding link nodes to the DOM for other browsers may be an idea.

  34. > Append them wherever you want.
    > If you have a standard layout naming
    > convention, append them inside your
    > container where appropriate.

    Sorry but you’re missing a point here – If *you* have a standard naming convention then you can put them what you want; but *I* (as the script) have no idea what your page looks like. I can’t put them just anywhere – I can only put them where you tell me.

    In other words, you don’t need to have empty containers at all .. you just need to tell the script the ID of an element into which you want the switcher form appended. The empty div is for convenience, but it can just as easily be an element that’s there already.

    I dig the rest of what you’re saying though, and that shouldn’t be a problem. But no need for createStylesheet or any other proprietary arcana – a script can load a stylesheet by chaning the HREF of an existing LINK element, and that’s how it’s going to work.

  35. A very welcome return for ALA and Zeldman.com
    … Great tutorial, as ever.

    You were missed by us all!

  36. It is great to see another article on ALA.

    I hate to be a killjoy but aren’t style switchers better done server side? I can’t really see the point of doing it with JS when is so easy in PHP.

    Oh well thanks for the great article!

  37. @ Mark Wubben: Driving today huh? 😉 There will be updates to memory leak soon on either Cake’s site (http://www.brothercake.com) or/and my own (http://www.stuffandnonsense.co.uk). Plus there is also an update for when you don’t wish to include the switcher controls on every page (as on my company site (http://www.malarkey.co.uk)

    @ Paul “the tree” Carpenter: Personally I feel that style-switchers are profoundly client-side solutions, but look out for a PHP and ASP version in the next few weeks. 😉

  38. >Sorry but you’re missing a point here – If
    >*you* have a standard naming convention then
    >you can put them what you want; but *I* (as the
    > script) have no idea what your page looks
    >like. I can’t put them just anywhere – I can
    >only put them where you tell me

    Pretty much agreed. I would however, use a small custom script per project in this case.

    You are correct in saying the script has no idea what the page has. However, the page, and markup should really have nothing to do with, or knowledge of the scripts in use other than a reference to them (or a few key variables defined at page level at worst).

    As I said before, its a fine line :). How many ways can you skin a cat?

    If I add this script do i have to change the header section of my site, or the body content and header section of each individual page?

    I’m glad the crap IE specific stuff is not required. It erks me that it was ever invented/implemented.

  39. Very good article!

    We’re nearing the day when display content and style will be user preference and less server dependent. As feed standards like RSS and Atom evolve and ontologies like RDF and OWL gain acceptance, the web will be a much more fluid experience combining knowledge, content and stype at the desktop.

  40. Great technique – thanks for the article.

    (Brian – you need to print the page and view the page in a browser with a projection to see the effect of the second and third dropdowns.)

  41. As everyone else I’m very happy to se ALA back in business. And what a great article 🙂

    Your technique (slightly modified) will save a project I’ve been working on (on and off) for the last year. The project is almost finished except for a couple of strange bugs in Safari we havn’t been able to solve. But you have. Thank you for that.

    I will need to create a variant that loads several css-files to make it work. The main reason for this is as someone else stated, maintainance problems on small sites that grow big. As a principle we also organise small sites the same way as big ones.

    And great of you to provide a garbage collector. Its easy to write one but if you’re not familiar with the concept as most web-programmers seems not to be its easy to walk into a prorietary-code-trap.

    So, great job and if you beat me on the multifile thing I’ll probably use your stuff for that to.

  42. @ Rasmus: A multi-file option, along with a raft of other enhancements are on there way.

    @ All: I personally would be very interested to see how/if this thing is being used in the wild. If anyone has examples, would you post them or send me a link?

    Have fun

  43. I Like it although I’m a little troubled by 2 things. (nothing to do with the code or the mark up of course :-)). 1). It lets the browser designers off the hook in coaxing them to adopt the ‘built into the browser’ style sheet switching that works so elegantly when done right. 2). It also means that you have to have form elements on your page where you might not want them. It still represents a move forward though..

    Robert

  44. This is a great technique, even better (or so it seems) than the original switcher idea. Thank you so much…

    …but is it possible to make it even more flexible?

    What I want to do, is set this up so that the first selector sets a “theme” for a page (with the page changing ala Zen Garden) and a second that sets “visibility” for menus and content (changing text size and backgrounds perhaps).

    Maybe the second selector would alter the value of an “interior DIV”, so that statements in the CSS might be something like…

    body.theme1 {

    body.theme1 largeText{

    body.theme1 highContrast{

    body.theme2 {

    body.theme2 largeText{

    …and the second and third values would only be applied if the second selector was set to “largeText” or “highContrast”.

    I’m still a beginner with CSS, so I’m not quite cluey enough work out the syntax, but I can see the possibilities. What a great way to make websites more flexible and accessible!

  45. I was reviewing previous comments and noticed that some people were worried about huge and unwieldy CSS files if ALL the coding is placed into one file.

    I wanted to see if it had to or not, as well. I’m about to reconstruct several sites of mine into one big homesite, and wanted to keep the styles I’d developed so that users could pick any style they wanted. I didn’t want to put all the coding into one CSS file either.

    However, the following is quite simple and seems to work on my browser (Maxthon, an IE overlay). In the HTML page, change the style links to something like:

    Then, in theme1.css you have coding like…

    @media screen {
    body.theme1 {…}
    body.theme1 a { color : #fff;}.
    .
    .
    .
    }

    …and in theme2.css you have something like…

    @media screen {
    body.theme2 {…}
    body.theme2 a { color : #000;}.
    .
    .
    .
    }

    …and that’s it. See, all the code can be kept as separate as you want.

  46. Even with your solution, Laura, the user still ends up loading all the styles that they may never use… imagine if you went to the zengarden and downloaded hundreds of stylesheets before the default one appeared! Obviously, there it’s a server-side solution, not a javascript trick, but the idea remains: only download the content the user wants.

    Although this is cool, I still maintain that it has no real place outside of a nifty effect on portfolio blogs. Yes, Wired does it, but I don’t think corporate sites are suddenly going to be jumping on the bandwagon with on-page font controls.

    As above, this has the most potential as a way to control something like colours or ‘what to print’ on a page. For example, an on-page tickbox could switch all text to black in the print-stylesheet, making for a much higher quality output.

  47. I can see now that you’re right, in that the technique is best used for small variations, rather than major ones, and swapping in whole stylesheets is better done using the original switcher.

    Thinking about the problem this morning I realised that there might be another way of doing this. On reflection, the advantage of using the original technique is that all the definition of which styles are used, and how the list is presented, is kept in the one javascript file, and not in the actual webpages, where they’d have to be updated manually. So only one or two files are altered, instead of who knows how many.

    Why not have the javascript just reset which stylesheet file is loaded (or reloaded with the refreshed page)? After all, if the whole switcher box code is generated from javascript on the fly, couldn’t the style declaration also be? That way, you only have one stylesheet loaded at any one time.

  48. “Pretty much agreed. I would however, use a small custom script per project in this case.”

    Not worth it. Consider the weight of that vs the customization of adding a simple, empty

    .

    As for examples in the wild… mayhaps soon. This done mused me good. 🙂

  49. While re-reading the comments, Laura’s in particular, I was struck by an idea that might work, can’t you have a main css file to use this technique, and then

    @media screen {
    import url(“style1.css”);
    }

    @media screen {
    import url(“style2.css”);
    }

    If you want to offer multiple CSS files. The only draw back is these CSS files still need the classes that must be appended to make this script work, or can this script be reworked so that it disables the styles from one style-sheet when the new one is enabled? If that were possible, then it would also be usefull to then include the other pages as alternate style sheets for UAs like Mozilla and Opera that offer the ability to change the style.

    Hmm, this may not be as usefull as I originally thought it might be…

  50. >> Pretty much agreed. I would however, use a
    >> small custom script per project in this case.

    > Not worth it. Consider the weight of that vs > the customization of adding a simple, empty

    .

    Of course its worth it. Simple concepts of programming are seperation of business logic from content from layout.

    If you put the divs in the page you are semi merging business logic and layout and content all into the html. BAD BAD BAD. Sure its “easier” short term.

    What happens if you have 4500 pages in an intranet, perhaps using 100 or so templates.
    What happens if I need to add another div?

    What happens if I want to update my script on 2 projects that both have 4500 pages, and a few hundered templates?

    Thats a lot files to change to add, modify or remove the solution, rather than a 1 program script, and 1 program insertion script.

    Remember the KISS principle. If you enforce seperation … then everything “theoretically” should be simple (and is 9/10 times). The important thing is to keep architecture ideas simple. Nitty gritty, and specific implementation can be complicated, but stick to the basic concepts.

  51. (It doesnt have to be an intranet.. not sure why i put that as the example above, especially since… bandwidth is generally a lot more generous, and browsers are more controlled in those environments. It could be any site, a large corporate with a few thousand pages whatever :)).

    I have some rather strong opinions on these types of things (which may well blind my common sense, but im not sure :)) because iv spent the last 2 years “rearchitecting” solutions to be more manageable/upgradeable (on all tiers).

    It’d be great to be able to write something new :).. ill have to bug my employer =]

  52. Works fine in Safari 1.2.3. When Javascript is switched off, the text “To see the effects of print media switching…” is visible even when the dropdown menu does not exist. This is of course the test page only, but maybe you could add a “document.write” for adding text and other related things that make sense only when Javascript is available, so they would not be rendered at all when JS is off.

  53. found an example of a switcher used by one of Australias largest news papers.

    http://www.theage.com.au

    It works for me 🙂

    Im not a fan of the specific implementation (hard coding in the controls), but the functionality is there.

  54. @Mike Purvis – well it is kind of a niche thing at the moment, but there are lots of uses beyond straight design switching. There are the print controls you mentioned; there could be buttons for changing screen fonts, or controlling the output and layout of a web mail interface; there could be projection media options that turn a website into a slideshow at various formats. These are the kind of things I ultimately had in mind, but whether any of them will become mainstream things, I don’t know …

    @Laura, Seth and Brian — I think there is mileage in that idea. The first step would be restricting the include format to elements, one for each media or switcher control, and named by the same naming convention, something like this:

    Then the script can dynamically reload the stylesheet in each link as its changed – so the option “high-visibility” equates to a stylesheet called “screen-switcher-high-visibility.css”

    Now whether the BODY classname paradigm would still be required … I’m not sure, possibly not. Find out when I try it …

    The bottom line is – yes, multi-sheet loading capability is absolutely necessary, and will be forthcoming. I’ll post a prototype on this thread before release, if that would helpful? So you can see if it meets your expectations.

    @Ned — I don’t understand what the big problem is with these empty divs. You don’t have to have them. They’re optional – not required. All you need is an element into which to append the switcher control, but that can be anything – it can be an element that’s already there.

  55. It’s a shame you’ve abandoned the one thing that made the original switcher such a great piece of work – the standards upon which the switcher was built.

    The original switcher can be adapted to fix many of the problems you have highlighted such as using A tags, see http://jon.dowland.name/ for an example.

  56. > The original switcher can be adapted
    > to fix many of the problems you have
    > highlighted

    It can’t be adapted to support multi-media capability, because the semantics have no scope for it, and that’s why we had to abandon it.

    If there is a way to acheive this without abandoning those semantics, I’m very happy to hear about it ..

    Nonetheless, the multi-sheet version that’s coming next will have the capability to use alternate stylesheet semantics for one chosen media type, if you wish.

  57. @James: What I’m trying to say is that addition of the script to a large project would be tedious UNLESS you were creating the containers on the fly. At the moment, you backout if they dont exist.

    These could be created with a custom “insertion” script that says, “ok, regardless of the markup, I’m going to add these controls to the page in the “such n such” container” (and if the container doesnt exist, you make one on the fly).

    Do not depend on markup.

  58. @ Ned Collyer: Ned, the latest version of the script posted at the links above may resolve your issues.

    As we have implemented it at http://www.malarkey.co.uk, we have the switcher controls on only one ‘customise this site’ page. Then, we included just the script on the other pages (no switching controls) and voila.

  59. And it may well be me …. but it’s like this:

    When you create an element in the DOM you have to append it somewhere. Where do you append it, if not to an element with a named ID?

  60. Thats the “custom insertion script” (per project) 🙂
    (Different locations for different markup = custom script for the project to determine location, or which div, where needs to be appended).

    Currently, the implementation is IN the source file. The implementation also depends on the markup. Hence, the JS source depends on the markup.

    The implementation should be seperated from your source (different file), so that either can be modified in isolation.

  61. Nice article … but I still do prefer CSS-only (no-JS) solutions, since I can’t see any reason for not including alternate styles in the HTML markup.

    RE: Firefox…
    The @media=print style can be seen, if you change the choice in the drop down and then choose File Print Preview.

    Nice to have ALA back 🙂

  62. @Ned – no, the implementation does not depend on the markup. The JS has a single variable (an argument passed to the object) by which you specify where to put the switcher control. If you want that value determined by the result of another process, that’s up to you, but the script itself is fine.

    @Fritz – because there’s no way to select those alternate styles for more than one media indendently.

  63. Sorry, because my last comment reads a little pissy.

    What I mean is that, although the script does have a dependence to the structure of the markup – it wants there to be an element with a named ID, or not, with no in between judgement – that’s as good as a generic script can ever be.

    If you want to modify it for your needs to make structural judgements, that’s cool, but it’s way beyond the scope of the core script – it would take a ridiculous amount of code, almost a whole meta-language, just to describe how it makes these judgements, and it would still get it wrong most of the time.

    As I’m sure you appreciate, writing scripts for other people to use is completely different from writing something for your own site. You can second-guess yourself, but I can’t second guess everybody.

    Ultimately, there has to be a point of distillation – a place where you tell the script what to do for a certain decision it can’t make itself. There’s no way around that … and this is (one reason) why elements can have ID attributes at all.

  64. great article. after the first style switcher article, i used the same approach to implement color palette switching for a number of my projects. with a single click, the sites’ entire color scheme can change from half-a-dozen options. many thanks, ala. you help us not-so-creative people become more creative.

  65. I’m with you, Ned, I am. But I feel like you’re blinded by something here, not sure what… 😉 But considering your comments:

    “What happens if you have 4500 pages in an intranet, perhaps using 100 or so templates.
    What happens if I need to add another div?

    What happens if I want to update my script on 2 projects that both have 4500 pages, and a few hundered templates?”

    That sounds like a job solved by some smart template architecture, and a global include. 🙂 Yes, that of course doesn’t account for the situation where you spend two years salvaging a monster, but *nothing* is going to be easy in that situation! You’re fixing what makes slick implementations like this bothersome.

    Besides, somebody made a point about how you’d determine where to create these in the absence of the

    s… yes, you could do it programmatically, but then I think it goes beyond the scope of many ALA readers and developers in today’s world(myself included) which means it makes implementation more hunt-and-peck than plug-and-play. 🙂

    But believe me, I’m with you. I’m also learning to better realize how to make compromises for the greater good, and I think this is an example of that.

  66. Thanks for the clarification Malarkey… I haven’t tried using non-screen media types yet and so hadn’t experiend the limitations of the previous switcher.

    I look forward to a future revision which recaptures the LINK tags 🙂

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

Nothing Fails Like Success

Our own @zeldman paints the complicated catch-22 that our free, democratized web has with our money-making capitalist roots. As creators, how do we untangle this web? #LetsFixThis