Placed in: Home arrow Programming arrow Webdesign arrow Create a better jQuery stylesheet switcher
Create a better jQuery stylesheet switcher

Style Sheet switchers (or "colour theme choosers") are not really that new. Apart from that fact, they still are pretty fun to use and cool to see. I was wondering how jQuery could help me achieve this technique. While searching, I came across several solutions.

There is a problem when using these techniques, which I will explain later. I created a little work-around to create a better jQuery stylesheet switcher. We'll simply change some colours for the user!

jQuery stylesheet switcher

Make sure to check out the demo to view what we're trying to accomplish.

Demo jQuery stylesheet switcher   Download jQuery stylesheet switcher

The cute little monsters used in the demo are created by Fast Icon (Dirceu Veiga). Now, let's take a look at how you can create something like this yourself!

Normal way

First, I'll show how jQuery users normally would change their CSS file.

HTML

This is the trimmed down version of the HTML file. As you can see, there is one style.css placed in the head and there are three links to color changers.

 
<html>
<head>
   <link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="colorchanger">
   <a class="colorbox colorblue" href="?theme=blue" title="Blue Theme"></a>
   <a class="colorbox colorgreen" href="?theme=green" title="Green Theme"></a>
   <a class="colorbox colororange" href="?theme=orange" title="Orange Theme"></a>
</div>
</body>
</html>

Nothing really fancy going on here - just the markup that we need for the page.

CSS

Now straight to the important part of the CSS file: The colorchanger. We'll turn the links into block elements.

 
/* COLOR CHANGER */
#colorchanger { float:right; }
.colorbox { width:20px; height:20px; border:1px solid #050505; float:left; margin:5px; cursor:pointer; display:block; }
.colorblue { background-color:#bfe1f1; }
.colorblue:hover { background-color:#90bcd0; }
.colororange { background-color:#F69C3A; }
.colororange:hover { background-color:#FF5C01; }
.colorgreen { background-color:#78A848; }
.colorgreen:hover { background-color:#189048; }

As you can see, the boxes each have their own color and hover effect. We'll now use jQuery to actually change the stylesheet when the user clicks on one of these links.

jQuery

After loading jQuery, we can now use it's power to change the link-element in the HTML-head (the place where we defined the first CSS sheet: style.css).

 
google.load("jquery", "1.3.1");
google.setOnLoadCallback(function()
{
   // Color changer
   $(".colorblue").click(function(){
      $("link").attr("href", "blue.css");
      return false;
   });
   
   $(".colorgreen").click(function(){
      $("link").attr("href", "green.css");
      return false;
   });
   
   $(".colororange").click(function(){
      $("link").attr("href", "orange.css");
      return false;
   });
 
});

This works great! Every time the user clicks on one link, the stylesheet gets replaced. Now the only thing we have to do, is define how the CSS should look like when switching colours.

The problem

There are two problems when looking at this solution: One small one, and a bigger one. The small one, is that the whole style.css gets replaced with the new CSS file (for example: blue.css). Since this new CSS file needs to be downloaded and parsed by the browser, the user will see a little flickering; A split second of the "naked" HTML file (no CSS).

But there is a bigger problem when using this solution. The whole style.css gets replaced, which means that all your CSS definitions will get replaced too. Everything you already set for body, #wrapper, #sidebar (like fonts, floats and sizes) in style.css will be gone as well.

"But you can copy the whole style.css content to the other style sheet files and change the colours, right?" That's absolutely true. But, what will happen if one style sheet would change? You would have to change all other CSS files which will cause loads of work. Also, you're not really saving bandwith with almost duplicate CSS.

The solution

I found a solution for this problem. The key lies in the fact that there are two ways of adding CSS to an HTML page. The normal way, is by using link rel='stylesheet'. The other way is using the style element.

We're going to use this difference to our advantage. We'll create one base CSS file (style.css) where we're going to place all CSS definitions except for the colours. Each colour gets his own CSS file that we're going to switch using jQuery.

HTML

We'll change the HTML a little bit to make this technique work.

 
<html>
<head>
   <style type="text/css">@import url("style.css");</style>
   <link href="green.css" rel="stylesheet" type="text/css" />
</head>
<body>
   <!-- Body contents here -->
</body>
</html>

Now, when we use the color changer, only the green.css file gets replaced by the other CSS file. This is how they can look like:

style.css (sizes, fonts etc.)

 
h2 a { display: block; margin: 0 0 30px 0; font: italic 45px Georgia, Times, Serif;
        text-align: center; }
#wrapper { width:940px; margin:40px auto; background-repeat:no-repeat; }

green.css (colours only)

 
h2 a { color: #78A848; }
h2 a:hover { color: #189048; }
#wrapper { background-image:url("images/monster_green.png"); }

That's all! Now, when the user changes the CSS files, only the colours get changed. Also, you can easily change the style.css file without having to make the same change in all other CSS files.

Conclusion and Download

Now we also need to set a cookie to save any colour changes the user made, so the next time the proper CSS gets loaded right from the start. Other than this, I think this is a pretty nifty way of changing CSS files

Demo jQuery stylesheet switcher   Download jQuery stylesheet switcher

What do you think? Would you do it any other way, or are you going to use it in your next project?


Tags:  css stylesheet switcher jquery webdevelopment

Interested in this topic? You might enjoy another article I've written called

Did you like this article? Subscribe to my feed or email to keep updated on new articles.

Spread the word and submit to:
Digg!Reddit!Del.icio.us!Facebook!Technorati!StumbleUpon!Newsvine!Furl!Ma.gnolia!
Comments
Add NewSearchRSS
Kyle Kinnaman - add an ID rather than use @import   2009-09-28 20:31:30
Gravatar image You can also add an ID or class to the style to be switched and forgo using @import to load the initial css.

header:
Quote:
link href='style.css' rel='stylesheet' type='text/css'
link id="css_color" href='green.css' rel='stylesheet' type='text/css'


js:
Quote:
// Color changer

$(".colorblue " ).click(function(){

$("#css_color " ).attr("href", "blue.css " );

return false;

});

It works in Firefox - I didn't test other browsers.
Marco - Whoah - thanks!   2009-09-28 20:33:12
Gravatar image Thanks Kyle! I tested that before, but for some reason, it didn't work for me. That's why I created the work-around with @import.

I must have done something wrong, thank you for checking it out! Also, I formatted your comment a bit.

Big thanks for helping me (and the community)!
Jack - Perfect!   2009-09-30 11:44:14
Gravatar image Ah, this is ideal and perfectly timed! Literally just working on a site that I was about to add a colour style switcher to and happened to skim through my feeds and there this post was!

Unfortunately I am using a CMS which requires a lot of different css files for different things so this initially just blanked the page - however, Kyle Kinnaman fix there works perfectly so this is absolutely ideal.

Thanks for the guide, files and solutions!
Janko   2009-09-28 21:38:54
Gravatar image Great example, Marco! I really like the demo :)
webmasterdubai - webmasterdubai   2009-09-28 21:47:23
Gravatar image nice work and good way to use style sheet switcher.
Bogdan Pop   2009-09-29 08:52:21
Gravatar image Wouldn't it be simpler to add the @import url("style.css " ); into the color css files?

Load by default green.css which has @import url("style.css " ); on the first line. Then using jQuery you switch the style to blue.css which also contains @import url("style.css " ); on the first line, or whatever. Therefor, you make all changes into style.css and keep the colors in their specific css file.
Marco - Would work   2009-09-29 10:19:13
Gravatar image That would work indeed, but there is a downside to this solution. Since the browser would fully have to parse the "blue.css", the user would also see a slight "flickering" of the page (CSS-less page).
Dan - Why is this happening   2009-10-10 08:18:36
Gravatar image When I tested this on my site, the following line is being added to my HEAD (by doing a simple inspection with Firebug):



This seems to be overwriting by other style sheet references, rewriting all hrefs of all style sheets.

Example Before:



Example After:




Any ideas?
Dan - whoops - redo   2009-10-10 08:24:32
Gravatar image script.js adding line:
link rel="stylesheet" type="text/css" href="css/green.css" media="all"

Before:
link href="css/mystyle.css" type="text/css" rel="stylesheet"
link href="css/green.css" type="text/css" rel="stylesheet"

After:
link href="css/green.css" type="text/css" rel="stylesheet"
link href="css/green.css" type="text/css" rel="stylesheet"
link rel="stylesheet" type="text/css" href="css/green.css" media="all"
Dan - Sorry   2009-10-10 08:29:07
Gravatar image Sorry. just saw Kyle Kinnaman's firs post. doh!
Anthony Fryer - sorted one of my problems, can you help with the n   2009-10-21 15:15:50
Gravatar image The idea to get rid of the flicker of unstyled content works a treat for a site I am currently working on. So you may also know the answer to my second problem?

I have a color changer and a font re-sizer. If they choose a different font then the font increases or decreases, if they choose a color background it changes background and foreground color, however it loses any font size preference?

How could I get it to work so I can choose both a different background color and a different font size from different stylesheets at the same time?

Any clues?
Jehu - not persistent   2009-10-21 16:39:04
Gravatar image First: Thank you for this tutorial.

You say no word about persistence. On demo-page the links have href="#", so a click has no impact. But if you make a page reload, the default style is shown again.

The choosen style should be saved in cookie by javascript [1] to make it work on real sites.

Regards
Jehu

[1] see http://www.quirksmode.org/js/cookies.html
Marco - Below   2009-10-21 20:02:13
Gravatar image Hi Jehu! Thanks a lot for your comment.

I did mention setting the cookie - right below "conlusion and download" ;) . This was just to show how to make a stylesheet switcher, but it's not fully implemented to make it usable. I hope you understand :) .
Rick   2009-10-28 15:21:01
Gravatar image This is a pretty niffy idea. One thing that bugs me is when you change the style it has to load a different background image there is some lag. A way to get rid of this is to creat a span with that img and change the position of the image for the different styles. B)
Ramil - Don't use @import   2009-11-05 09:27:59
Gravatar image I'm looking for a good jQuery style switcher, found yours but seems there's a problem:
1.) non-persistent - no cookie
2.) don't use @import - http://stevesouders.com/blog/2009/04/09/dont-use-import/
wespai   2009-12-25 10:30:13
Gravatar image thx collect it to ajax.wespai.com
Dennis   2010-01-20 09:07:50
Gravatar image Very nice!

I am pulling css specifics from a DB and want to open my page with the css values from that entry. (logo position, font,color).

Have you seen any examples ?

Thanks
Ege - why not use classes?   2010-01-20 16:13:19
Gravatar image you can define some rules simply according to your body tag's class:

(ie )

Code:
.blue a:link {
color:blue;
}


and

Code:
.orange a:link {
color: orange;
}


and

Code:
$(".switcher";).click(function() {
$("body";).toggleclass("blue orange";);
});


any downsides of this?
Andy Freeman - Almost there with DB solution   2010-02-04 12:18:07
Gravatar image Ok am pretty much there with my working example of storing the colour.css in a DB then loading the page with the value from the DB.

One bit that is really stumping me is this

When i run it works fine

Code:
    
$(document).ready(function() {

$("#css_colour";).attr("href", 'CSS/Themes/red.css');

});


When I run it via a variable it does not work

$(document).ready(function() {

var MyClientSideVariable = 'CSS/Themes/red.css';
$("#css_colour";).attr("href", MyClientSideVariable);

});

I am very new to jQuery/JScript so would really appreciate if anyone can assis me with fixing this.

If i can resolve this I will be delighted, as i know i can set the MyClientSideVariable = thestoredDBvalue

Many Thanks
Andy
Curtis - Slight Edit   2010-03-22 12:45:40
Gravatar image I found this quite useful so thought I would post my little edit to it.

First, I add in the default theme with an ID. (as per the first post by Kyle so I don't get my normal style sheets removed)
Code:




Then I add my Theme switch area with IDs for each theme.
Code:


Theme 1
Theme 2
Theme 3



And then rather than add a separate script for each theme, I just have one which grabs the id of whatever is clicked and inserts it into the link.
Code:

$("ul#themes li a";).click(function(){
var theme = $(this).attr("id";);
$("link#themeswitch";).attr("href", "" + theme + ".css";);
return false;
});
Curtis - re: Slight Edit   2010-03-22 12:48:14
Gravatar image Well, that didn't work. Even with the pre and code tags, it still stripped it all out.
Aman - Cool Plugin   2010-08-18 16:47:03
Gravatar image Hi

I like this plugin.I have Also 10+ Jquery Style Switchers plugins please see:-

http://jquery13.blogspot.com/2010/08/10-jquery-style-switchers.html


Thanks
Aman
Read more...
Name:
Email:
  Gravatar enabled.
Website:
Title:
UBBCode:
[b] [i] [u] [url] [quote] [code] [img] 
 
 
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch:
:(:shock::X:side::):P:unsure::woohoo::huh::whistle:;):s
:!::?::idea::arrow:
 
Unsubscribe from e-mail notifications.
 
< Prev   Next >
Subscribe

Get updates from this website along with 5304 others.