How To Create An Amazing jQuery Style Switcher

In this tutorial I will be showing you how to create a style switcher using jQuery and PHP. The end result will be an unobtrusive & entirely degradable dynamic style switcher which will be quick and easy to implement.

Step 1: The HTML

First, we need to create our basic HTML file and save it as index.php:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>Style Switcher</title>
		<?php
			// Checks for, and assigns cookie to local variable:
			if(!empty($_COOKIE['style'])) $style = $_COOKIE['style'];
			// If no cookie is present then set style as "day" (default):
			else $style = 'day';
		?>

		<!-- StyleSheet -->
		<link id="stylesheet" type="text/css" href="css/<?php echo $style ?>.css" rel="stylesheet" />

		<!-- jQuery -->
		<script type="text/javascript" src="js/jquery.js"></script>

		<!-- Our plugin -->
		<script type="text/javascript" src="js/styleswitcher.jquery.js"></script>

	</head>
	<body>
		<div id="container">
			<h1>Style-Switcher Example</h1>
			<ul id="nav">
				<li><a href="#">Home</a></li>
				<li><a href="#">About</a></li>
				<li><a href="#">Services</a></li>
				<li><a href="#">Products</a></li>
				<li><a href="#">Links</a></li>
				<li><a href="#">Contact</a></li>
			</ul>
			<div id="banner"></div>
			<div id="content">
				<h2>NETTUTS Tutorial Example</h2>
				<p>Page content...</p>
			</div>
			<div id="foot">
				<p>Footer stuff...</p>
			</div>

			<!-- StyleSheet selection: -->
			<div id="style-switcher">
				<h4>Choose your style:</h4>
				<ul>
					<li id="day"><a href="style-switcher.php?style=day">Day</a></li>
					<li id="night"><a href="style-switcher.php?style=night">Night</a></li>
				</ul>
			</div>

		</div>

		<script type="text/javascript">
			$('#style-switcher a').styleSwitcher(); // Calling the plugin...
		</script>

	</body>
</html>

You’ll see that there is some PHP up there just below the title attribute in the head. It’s very simple – all it does is check for a cookie called “style” – if it exists then it assigns it to the local variable (also called “style”) and if the cookie doesn’t exist, it assigns the default theme (“day”) to the $style variable. This variable is then echoed out within the href attribute of the link element (href="css/<?php echo $style ?>.css").

You’ll see that the style-switcher div is included above in our HTML. There is no need to add this using JavaScript because the method we’re using will allow the style-switcher to work when JavaScript is disabled. The two links (night & day) take the user to a file called style-switcher.php with an appended query string specifying the corresponding theme (e.g. href="style-switcher.php?style=day").

I’ve also called the a jQuery plugin called styleSwitcher. This has not been developed yet (well, it will have by the time you read this), so hold on! … We will be writing this plugin in step 4 of this tutorial.

Step 2: The CSS

Now, we need to create a couple of CSS StyleSheets for our HTML. I’ve decided to create just two StyleSheets – one will have the theme of “Day” and the other will have the theme of “Night” and I’ve named them appropriately. (day.css & night.css)

The Day theme:

Night Theme

The Night theme:

Night Theme

It’s best to start with one style and then copy across all the selectors to the alternative StyleSheet – and then all that needs changing are the various CSS rules and declarations. Obviously you can have as many StyleSheets as you want but in this tutorial we’re using two for illustrative purposes. Plus night and day go well together as a duo!

day.css:

#dummy-element{width:2px;} /* Necessary to check if StyleSheet has loaded */

/* Quick Reset */
body,ul,ol,li,img,form,p,h1,h2,h3,h4,h5,h6,blockquote {
	margin: 0;
	padding: 0;
	border: none;
	list-style: none;
	font-weight: normal;
}

/* General / Header */
body {background: #98beeb url(../img/day-body-bg.jpg) repeat-x; }
#container {
	width: 60%;
	margin: 0 auto;
	min-width: 400px;
	max-width: 800px;
	position: relative;
}
h1 {
	text-align: left;
	text-transform: uppercase;
	color: white;
	font-size: 1.4em;
	padding: 45px 30px 10px 30px;
}

/* Navigation */
#nav {
	padding: 5px 5px 0 0;
	overflow: hidden;
}
#nav li {display: inline;}
#nav a {
	float: left;
	color: #6195ce;
	font-weight: bold;
	text-decoration: none;
	padding: 3px 6px;
	margin-left: 5px;
	background: white;
}
#nav a:hover {color: #2c5a8c;}

/* Banner */
#banner {
	height: 125px;
	background: url(../img/day-banner.jpg) center;
	border: 5px solid white;
	clear: both;
}

/* Content Area */
#content {
	border: 10px solid white;
	background: white;
	color: #2c5a8c;
	margin: 5px 0;
}
#content a {font-weight: bold;}
#content a:hover {text-decoration: underline;}
h2 {
	padding: 0.3em 0;
	font-size: 1.4em;
}
p {padding: 0.3em 0;}

/* Footer */
#foot {
	background: white;
	color: #1f3a57;
	text-align: center;
	border: 10px solid white;
	clear: both;
}
#foot a {
	text-decoration: none;
	font-weight: bold;
	color: #2c5a8c;
}
#foot a:hover {text-decoration: underline;}

/* Style-Switcher */
#style-switcher {
	position: absolute;
	width: 100%;
	top: 0;
	left: 0;
	right: 0;
	height: 34px;
	background: #79a3cc url(../img/day-ss-bg.jpg);
	border-bottom: 1px solid white;
}
#style-switcher ul {
	border-right: 1px solid white;
	float: right;
}
#style-switcher h4 {
	display: inline;
	color: #153c67;
	font-weight: bold;
	line-height: 34px;
	padding: 0 10px;
	float: left;
	border-left: 1px solid white;
}
#style-switcher li {display: inline;}
#style-switcher li a {
	float: left;
	line-height: 26px;
	color: white;
	background: #90a6bb;
	text-decoration: none;
	padding: 0 13px;
	display: inline;
	margin: 4px 4px 4px 0;
}
#style-switcher li a:hover {background: #3a5a7c;}

night.css:

#dummy-element{width:2px;} /* Necessary to check if StyleSheet has loaded */

/* Quick Reset */
body,ul,ol,li,img,form,p,h1,h2,h3,h4,h5,h6,blockquote {
	margin: 0;
	padding: 0;
	border: none;
	list-style: none;
	font-weight: normal;
}

/* General / Header */
body {
	font-family: Calibri,"Arial Narrow",Arial,Sans-Serif;
	background: #072952 url(../img/night-body-bg.jpg) repeat-x;
}
#container {
	width: 60%;
	margin: 0 auto;
	min-width: 400px;
	max-width: 800px;
	position: relative;
}
h1 {
	text-align: left;
	text-transform: uppercase;
	color: white;
	font-size: 1.4em;
	padding: 45px 30px 10px 30px;
	font-family: "Times New Roman", Times, serif;
}

/* Navigation */
#nav {
	padding: 5px 5px 0 0;
	overflow: hidden;
}
#nav li {display: inline;}
#nav a {
	float: left;
	color: #010e2e;
	font-weight: bold;
	text-decoration: none;
	padding: 8px 6px 3px 6px;
	font-size: 0.8em;
	text-transform: uppercase;
	font-weight: 700;
	margin-left: 5px;
	background: white url(../img/night-nav-bg2.jpg) repeat-x;
}
#nav a:hover {color: #2c5a8c;}

/* Banner */
#banner {
	height: 125px;
	background: url(../img/night-banner.jpg) center;
	border: 5px solid white;
	clear: both;
}

/* Content Area */
#content {
	color: white;
	margin: 20px 0;
	padding: 5px 0;
	border-top: 4px double white;
	border-bottom: 4px double white;
	font-family: "Times New Roman", Times, serif;
}
#content a {font-weight: bold;}
#content a:hover {text-decoration: underline;}
h2 {
	padding: 0.3em 0;
	font-size: 1.4em;
}
p {padding: 0.3em 0;}

/* Footer */
#foot {
	color: white;
	font-size: 0.8em;
	clear: both;
}
#foot p {
	text-align: center;
	padding: 0;
}
#foot a {
	text-decoration: none;
	font-weight: bold;
	color: white;
}
#foot a:hover {text-decoration: underline;}

/* Style-Switcher */
#style-switcher {
	position: absolute;
	width: 100%;
	top: 0;
	left: 0;
	right: 0;
	height: 34px;
}
#style-switcher ul {float: left;}
#style-switcher h4 {
	display: inline;
	color: white;
	font-weight: bold;
	line-height: 34px;
	padding: 0 10px;
	float: left;
}
#style-switcher li {display: inline;}
#style-switcher li a {
	float: left;
	line-height: 34px;
	color: white;
	text-decoration: none;
	padding: 0 4px;
	margin-left: 5px;
	display: inline;
}
#style-switcher li a:hover {
	background: white;
	color: #13181c;
	background: white url(../img/night-ss-bg.jpg) repeat-x left bottom;
}

This is not really a CSS tutorial so I won’t be delving into any of the above, but if you have any questions then please feel free to ask them in the comments section. And yes, I know that min-width is not supported in older browsers! ;)

Step 3: style-switcher.php

This is where we write the core functionality of the style switcher. It is actually just a few lines of very basic PHP code. You should create a new file called “style-switcher.php” and copy the following into it:

<?php
	$style = $_GET['style'];
	setcookie("style", $style, time()+604800); // 604800 = amount of seconds in one week
	if(isset($_GET['js'])) {
		echo $style;
	} else {
		header("Location: ".$_SERVER['HTTP_REFERER']);
	}
?>

So, what the above code does is assign the “style” GET variable to a local $style variable. In other words it will take the value of the style property within the query string (style-switcher.php?style=day). It then sets a cookie (for one week) called “style” – we will be able to retrieve this cookie on our main index.php with the code shown in step 1 (remember that little chunk of PHP in the head?). Next, it checks to see if “js” is appended to the query string. If it is then we know that JavaScript (which we have yet to write) has requested this PHP script. The else condition occurs when a user does not have JavaScript enabled and redirects the user to the referrer (i.e. the page they just came from) – this will become clearer once we’ve written the jQuery stuff!

Step 4: The jQuery stuff

You can, if you want, stop right here!… The solution thus far will work perfectly, but as I stated in the intro we are going to make it even cooler with some jQuery awesomeness! Not only are we going to allow the user to change their theme without refreshing the page but we are also going to add a really cool fading effect… I mean, what type of jQuery tutorial would this be if there was no fading!?!?

Obviously this is all possible without having to create a plugin but I thought it would be a good learning experience for all you, plus it allows us to adapt or transfer the code quickly and easily.

First off, let’s create a file called “styleswitcher.jquery.js”.

Making a new plugin in jQuery is extremely simple; all it takes is the following code:

jQuery.fn.styleSwitcher = function(){
	// The code goes here...
}

So, first we want to specify what happens when one of the StyleSheet links are clicked on (those within div#style-switcher):

/* "this" refers to each instance of the selected element,
 * So, if you were to call the plugin like this:
 * $('a').styleSwitcher(); then the following would occur
 * when clicking on any anchor within the document:
 */

$(this).click(function(){
	// We're passing this element object through to the
	// loadStyleSheet function.
	loadStyleSheet(this);
	// And then we're returning false.
	return false;
});

loadStyleSheet:

Now we need to write the loadStyleSheet function:

function loadStyleSheet(obj) {

	// Append new div to body:
	$('body').append('<div id="overlay" />');

	// Give body a height of 100% (to fix IE6 issue):
	$('body').css({height:'100%'});

	// Select newly created div and apply some styles:
	$('#overlay')
		.css({
			display: 'none',
			position: 'absolute',
			top:0,
			left: 0,
			width: '100%',
			height: '100%',
			zIndex: 1000,
			background: 'black url(img/loading.gif) no-repeat center'
		})

		// Now fade in the div (#overlay):
		.fadeIn(500,function(){

			// The following will happen when the div has finished fading in:

			// Request PHP script (obj.href) with appended "js" query string item:
			$.get( obj.href+'&js',function(data){

				// Select link element in HEAD of document (#stylesheet) and change href attribute:
				$('#stylesheet').attr('href','css/' + data + '.css');

				// Check if new CSS StyleSheet has loaded:
				cssDummy.check(function(){

					// When StyleSheet has loaded, fade out and remove the #overlay div:
					$('#overlay').fadeOut(500,function(){
						$(this).remove();
					});
				});
			});
		});
}

I hope the comments explained it sufficiently. The more attentive of you will have noticed that we are calling a currently undefined function (cssDummy.check()). Don’t worry because that is the next step…

cssDummy:

We need a way of testing whether a StyleSheet has loaded. If it has loaded then we can make the overlay div disappear, but if it hasn’t we have to keep on checking until it does load. I did a bit of searching around the net and found a reliable way of testing such a thing. It involves testing for the computed width of a dummy element. The width of this element will be defined in the CSS – and so the computed width of the element will only equal the width defined in the CSS when the StyleSheet has loaded. I hope you now understand why we had to include that “#dummy-element” rule in each CSS file…

So, here it is:

var cssDummy = {
	init: function(){
		// Appends "dummy-element" div to body:
		$('<div id="dummy-element" style="display:none" />').appendTo('body');
	},
	check: function(callback) {

		// Checks if computed with equals that which is defined in the StyleSheets (2px):
		if ($('#dummy-element').width()==2) callback();

		// If it has not loaded yet then simple re-initiate this
		// function every 200 milliseconds until it had loaded:
		else setTimeout(function(){cssDummy.check(callback)}, 200);
	}
}

And, right at the end of our plugin we’re going to call the cssDummy.init function:

cssDummy.init();

We’re done! The entire plugin now looks like this:

jQuery.fn.styleSwitcher = function(){
	$(this).click(function(){
		loadStyleSheet(this);
		return false;
	});
	function loadStyleSheet(obj) {
		$('body').append('<div id="overlay" />');
		$('body').css({height:'100%'});
		$('#overlay')
			.css({
				display: 'none',
				position: 'absolute',
				top:0,
				left: 0,
				width: '100%',
				height: '100%',
				zIndex: 1000,
				background: 'black url(img/loading.gif) no-repeat center'
			})
			.fadeIn(500,function(){
				$.get( obj.href+'&js',function(data){
					$('#stylesheet').attr('href','css/' + data + '.css');
					cssDummy.check(function(){
						$('#overlay').fadeOut(500,function(){
							$(this).remove();
						});
					});
				});
			});
	}
	var cssDummy = {
		init: function(){
			$('<div id="dummy-element" style="display:none" />').appendTo('body');
		},
		check: function(callback) {
			if ($('#dummy-element').width()==2) callback();
			else setTimeout(function(){cssDummy.check(callback)}, 200);
		}
	}
	cssDummy.init();
}

We can now call the jQuery plugin like this:

$('#style-switcher a').styleSwitcher();

Finished!

If you’re not sure about the file structure then download the src files to have a look. I hope you enjoyed reading through this tutorial. As always, if you have any questions feel free to ask them below! If you enjoyed this posting, please Digg it!


Related Posts

Add Comment

Discussion 96 Comments

Comment Page 3 of 3 1 2 3
  1. Ted says:

    Still no idea for automatic switch?

  2. Hi, this is just huge !

    I was just looking for a script like this one !

    i’ve just had few troubles with the cookie writing functions, but i finally managed to make it work perfectly with some research.

    thanks a lot, great job !

  3. hendo says:

    @ted –
    Instead of using a cookie to get the default style, use the php date() function to get a current timestamp…then with a simple if statement, you can set the corresponding style as the default.

    nice article champ

  4. FcPro says:

    Interesting.. Greet..

  5. graffiti says:

    nice,
    is the cookie setup fixed right now ?

  6. Sylvain says:

    This can be done completely client side with recent browsers (same thing as what Paul Gendek wrote above):

    http://www.alistapart.com/articles/alternate/

  7. thomas says:

    awesome plugin, but is there a way to completely refresh and reload the page before it’s faded back in?

  8. Joel says:

    Does this work with Jquery 1.3.1?

  9. cotton says:

    Hi, great tutorial!
    I saw someone else tried to implement it to a wordpress theme. I am also but without any success. It seems that the does not work. It comes out as …css/.css (without the night or day before .css) Is there any way around this?

  10. John S says:

    My loading div does not fadout, it just stays there. If I refresh the page the seleted style I shows correctly, so the php script is getting called and working. I also verified this with Firebug, the correct style is getting echo’ed by the php script, so I am assuming it has something to do with the checkDummy function not working correctly. I did add the dummy variable in all my css files, so I am at a loss. Any ideas?

  11. John S says:

    Looking through firebug I found my issue but can’t seem to figure out why it is occuring or how to solve it. Firebug says that it is trying to load my css file as blue .css with spaces instead of the correct file blue.css. Since it can’t load the file the cssDummy check goes into an infinite loop. Any ideas?

  12. Acr0nym says:

    Would it be possible to have on the click event to change html images as well. Example: to change to this way I won’t have to use css background images.

    Thanks in advance.

    • sam says:

      if you are using php, you could use the $style variable and some if else statements to output different html
      :)

  13. Mukarram says:

    excellent work –

    well my question is – can it change automatically from day to nite when time change ….or depends on user time periods ????

    please tell me or contact me at my mail address i.e.
    wings.of.designing at gmail dot com

  14. Very smart, going to try it now on one of my websites, i am sure my visitors will love it , thank you

  15. peter says:

    This is a great bit of work.

    How would you propose adding in an accessibility tweak to allow someone to change the stylesheet from the browser?

    This would involve adding a link to an alternative stylesheet in the head of the document which would be dependant upon what stylesheet is currently being used.

    So if the stylesheet is ‘day’ the following would be printed in the html .

    and if the stylesheet is ‘night’ this would be printed

    The benefit of this would be for those who like to change their stylesheets via the browser settings, so for example in Firefox i’d go to view > page style > and choose the alternative stylesheet available.

    Cheers

  16. Vitthal says:

    its having problem in ie.

    After select the night theme when i refersh the page is converted back into day??

    Do you have any solution for this. please help me out of this.

    Many Thanks

  17. molly says:

    are we any closer to solving the WordPress problem with this plugin? doesnt work for me on any WP install. javacsript on or off makes no difference. it is possibly in the setting of the cookie, but LiveHTTP headers tells me the cookie is being set.

  18. sam says:

    ok to get this working in WordPress you need to use this in the style-switcher.php (note extra slash in setcookie)


    $style = $_GET['style'];
    setcookie("style", $style, time()+604800,"/");
    if(isset($_GET['js'])) {
    echo $style;
    } else {
    header("Location: ".$_SERVER['HTTP_REFERER']);
    }

    the javascript part is still not working however, it fades to black then freezes. although when i reload the page, the style is changed.

    any help on getting this working in WordPress would be much appreciated!

    thanks!!

  19. Helen says:

    Very nice! Is there a chance to switch stylesheets automatically depending on the local time of the user?

  20. kilitx says:

    hi
    home.php

    Day/Night

    and

    style-switcher.php

    in not working. where do bugs.

    this a wordpress theme :)

  21. kilitx says:

    hi
    this is my home.php

    <div id="style-switcher">
    <h4>Choose your style:</h4>
    <ul>
    <li id="day"><a href="style-switcher.php?style">Day/Night</a></li>
    </ul>
    </div>

    and this is my style-switcher.php


    <?php
    $style = ($_COOKIE['style']=='day') ? 'night' : 'day';
    setcookie("style", $style, time()+604800, "/");
    if(isset($_GET['js'])) {
    echo $style;
    } else {
    header("Location: ".$_SERVER['HTTP_REFERER']);
    }
    ?>

    in not working. where do bugs.
    this a wordpress theme :)
    EDIT

  22. bucktaiwan says:

    Good job. Thank you.

  23. Blackdown says:

    Fade Out not fonctionnaly !

  24. Matt says:

    Hi, thanks for this script.
    However I’m having trouble with Cufon or SIFR text not taking new colors parameters when styleswitching, I’m oblige to refresh or hit F5 for this to work.
    Could you tell me what I can adapt.
    Because even if the new style are displaying ok, when i’m checking the source of my page, it’s still my older css that is showing up, meaning the problem is maybe a refresh problem or so on.
    Thanks to help!

  25. Matt – Have you tried using the Cufon Refresh Function? Cufon.refresh()

  26. GREAT work ! i hope if these things can also be used in blogger he he.

  27. Pete says:

    For some of those who experience an unchangeable black screen, check that you have added an id=”stylesheet” to the stylesheet link in your main page. I missed it.

  28. atilazz says:

    he best site that ever I saw.
    I wanted everything found here.
    love this site and tutorials.
    I introduced this site to all my friends,
    loooooooooooooooooveee them:D:-*

  29. Drewbiewan says:

    Anyone having troubles with fade out not working, if you changed your css directory, make sure you declare is in the javascript file.

    .fadeIn(500,function(){
    $.get( obj.href+’&js’,function(data){
    $(‘#stylesheet’).attr(‘href’,'PATH/TO/CSS/FILE’ + data + ‘.css’);

  30. Anton says:

    Is it possible to redirect, after clicking on day/night button

  31. BJNET says:

    Amazing script, i want to know that i am author at ThemeForest, so am i allowed to use this script with the theme which i am selling at ThemeForest.

    Thank you

    plz reply me soon coz my theme is about to be released and i am looking for a script like this.

  32. Thomas says:

    Hi, I used the style switcher and it works great for me, my only problem is that i want to keep the cookie ’style’ on the inner pages of my website but for some reason the value changes, displaying a different color that the one you choosed in the first place.

    ¿Can someone help me with that?

  33. Thomas says:

    I also noticed that in internet explorer the cookies from the style switcher go crazy. When i select a color and refresh the page, the cookie sets the value of the color i selected before that.

    Please help, i really need that to work

  34. BJNET says:

    Kevin Lofthouse,

    PLZ tell me what is the license of this script.

    Because i am asking this second time.

    Am i allowed to use this script with the theme which i am selling at ThemeForest.

    Thank you

  35. BJNET says:

    Oops, sorry i had to ask the Author..

    James Padolsey,

    PLZ tell me what is the license of this script.

    Because i am asking this second time.

    Am i allowed to use this script with the theme which i am selling at ThemeForest.

    Thank you

  36. Oussama says:

    Lol .. Day ‘n night

  37. Karl says:

    James, I just came across your style switcher and I have one question/comment.

    It seems to me that this technique is only good for brand new sites. Here’s why. If I already have an existing site that ranks high in search engines do I really want to change my URLs from *.htm to *.php?

    What do you think?

    Thanks, Karl

  38. Kath says:

    The jQuery version does work with Wordpress if

    a) you leave out the cssDummy check and
    b) only call the styleswitcher script from the start page / root directory because this part

    [code]
    // Select link element in HEAD of document (#stylesheet) and change href attribute:
    $('#stylesheet').attr('href','css/' + data + '.css');
    [/code]

    only seems to accept relative paths to the stylesheet directory. From any wordpress post/page the relative path to the stylesheet gets attached to the permalink and you’re bound to end up with a 404.

    I have tried using absolute paths for the stylesheet and for loading.gif but only get 404-errors for these too. Would be glad if anyone could come up with an idea cause I actually like the way the new stylesheet is faded in ;-)

  39. Kath says:

    Update: Now works well with Wordpress if I leave out the “cssDummy” stuff.

Comment Page 2 of 2 1 2

Add a Comment