A Simple jQuery Stylesheet Switcher

jQuery stylesheeet switcher

There are lots of reasons you might want to offer your users more than one CSS file for your website:

  • You want to offer a “stylish” low-contrast and an easy-to-read high-contrast version of your site.
  • You have many low-vision readers and want to give them easy access to a customized stylesheet with a larger typeface.
  • Your site is schizophrenic and you want to be able to change the look quickly.

Whatever the reason, it’s amazingly easy to create a function that swaps between multiple stylesheets using jQuery.

The first step of course is to build several different CSS files, which we’ll then swap between. Once that is done, we can dive into the XHTML and jQuery that makes the magic happen.

The XHTML

First, we need to create a set of links that will allow the user to swap between CSS files. You can make this as simple or as fancy as you’d like. For the sake of brevity, my links are simple:

1
2
3
4
5
<ul id="nav">
	<li><a href="#" rel="/path/to/style1.css">Default CSS</a></li>
	<li><a href="#" rel="/path/to/style2.css">Larger Text</a></li>
	<li><a href="#" rel="/path/to/style3.css">Something Different</a></li>
</ul>

Here I have three links, each with a “rel” attribute indicating which CSS file the link will load. Technically, I could have just as easily put this information in the “href” attribute, but I didn’t want to for one specific reason: if the user has JavaScript disabled and the CSS file is listed in the href, then clicking the link will send the user to the CSS file directly (not loading it like we intended). But our way, if JS is disabled, the user gets nothing at all: which is certainly preferable to the less savory alternative.

The jQuery

Like I promised, the jQuery is really simple:

1
2
3
4
5
6
$(document).ready(function() { 
	$("#nav li a").click(function() { 
		$("link").attr("href",$(this).attr('rel'));
		return false;
	});
});

This function waits until the document is loaded (generally an important step when interacting with the DOM), then attaches a click function to each of our nav anchors. The function basically says, “when someone clicks on this link, replace the link (stylesheet) tag’s href attribute with the contents of this link’s rel attribute.” The “return false” at the end just stops the browser from trying to follow the link.

Of course, you might have to get more detailed if you have more than one link tag, for example, but that’s easily done by giving the link tag a class (“changeme,” for argument’s sake), and writing something like this:

1
$("link.changeme").attr("href",$(this).attr('rel'));

And while this stylesheet switcher is already complete, we might want to give it some memory: after all, your users might get annoyed if they have to switch their styles back to their preferences every time they visit your site. For that, we’ll need to set a cookie. And to make that easier, I’ll use the jQuery cookie plugin (which I’ve talked about previously when building a popout ad).

With the plugin loaded, we can modify our jQuery thusly:

1
2
3
4
5
6
7
8
9
10
$(document).ready(function() { 
	if($.cookie("css")) {
		$("link").attr("href",$.cookie("css"));
	}
	$("#nav li a").click(function() { 
		$("link").attr("href",$(this).attr('rel'));
		$.cookie("css",$(this).attr('rel'), {expires: 365, path: '/'});
		return false;
	});
});

Now we have two statements. The first one checks as soon as the page is done loading to see if a cookie called “css” has been set. If so, it sets the stylesheet to be the one indicated in that cookie. Otherwise, it does nothing.

Our click function is much the same, except after we set the stylesheet, we also set a cookie. This cookie doesn’t expire for an entire year (and each time the user changes their stylesheet preferences, it would reset this timer), giving them a good 365 of CSS bliss.

Fine Tuning

There is one minor annoyance with this stylesheet switcher: there’s generally a flash of the “default” CSS when the user loads the page. That’s because the script waits until the document is “ready” before switching the link’s href. There is a way around this: moving the first “if” statement outside of the document ready function, like so:

1
2
3
4
5
6
7
8
9
10
if($.cookie("css")) {
	$("link").attr("href",$.cookie("css"));
}
$(document).ready(function() { 
	$("#nav li a").click(function() { 
		$("link").attr("href",$(this).attr('rel'));
		$.cookie("css",$(this).attr('rel'), {expires: 365, path: '/'});
		return false;
	});
});

Generally speaking, you don’t want to run any jQuery until your document is ready. However, so long as your jQuery comes after your link tag in your document structure, like shown below, this shouldn’t be a major concern:

1
2
3
4
<link rel="stylesheet" type="text/css" href="style1.css" />
<script type="text/javascript" language="javascript" src="jquery.js"></script>
<script type="text/javascript" language="javascript" src="jquery.cookie.js"></script>
<script>... your jQuery goes here...</script>

This means your jQuery will run before the document is done loading, and thus your link tag’s href will be swapped before your CSS has been applied. As I said before, it’s generally a bad idea to manipulate the DOM before document ready, but because we know the exact tag we want to manipulate and can place our jQuery below it in the DOM, we should be safe in this one specific instance.

Here’s an example if you would like to see this technique in action.

40 Comments

  1. On April 02, 2009
    11:39PM

    Brett Shegogue said:

    Great Article! Would there be an easy way to tweak this so say a different stylesheet shows up depending on the current date? Say if I want to have a different style sheet for different seasons? Or would that be a completely different beast?

  2. On April 03, 2009
    8:46AM

    Rob Glazebrook said:

    Hi Brett,

    It could certainly be done (in a couple of different ways). And this idea would serve as a good base for that endeavor. But I think all that might be too much information for a comment. Perhaps it will result in another article in the near future! :)

  3. On April 03, 2009
    9:10AM

    Brett Shegogue said:

    Yes, thats what I figured. I am just starting out (less then a year in web development) and I am doing a small 3 page site for a local lawn service for $150. So it is definitely more for the experience over the money. I was considering making different style sheets for the seasons, but feel it may be too much time for my compensation.

    Thanks for your help , I have been a subscriber for a couple of weeks now and really enjoy your stuff! Keep it up.

  4. On April 04, 2009
    12:00PM

    nady said:

    nice tutorial … thanks.

  5. On April 05, 2009
    10:03AM

    Casper Bang said:

    Thanks for the post. I just implemented something similar a few weeks ago (Not happy with the jquery-ui theme switcher) but did not solve the “page load reverts to default” problem. Thumbs up to your timing. ;)

  6. On April 07, 2009
    6:40AM

    Rahul said:

    Very interesting jquery feature of stylesheet switcher.

  7. On May 04, 2009
    8:25AM

    jefferis peterson said:

    Hi, I’m testing out your script on these 2 pages http://www.scholarscorner.com/debug.html and debug2.html. I used an older script on the rest of the site, but it doesn’t retain the user selection, I’m brand new to jQuery, thought I’ve developed for years. I’m not sure what I’m doing wrong but it doesn’t seem to be working. One question is, I don’t understand where you put the default CSS for the site. If all the links are relative by user selection, you’ll not have a CSS to start with.
    So I have
    in the header above the jQuery switcher function. And my user selectable links only result in an # added to the page url:

    change to Black
    change to White

    Any guidance appreciated.
    Jeff

  8. On May 05, 2009
    1:26PM

    Rob Glazebrook said:

    Hi Jefferis,

    I think the problem is in your document.ready script. You’re telling the script to look for my ‘default’ (read: made up) navigation structure, which consists of an unordered list with an ID of “nav”. You don’t have any such element on your page. You’ll need to edit that $(“#nav li a”) bit to read something that actually exists on your page. Because your page’s navigation is so complex, you probably don’t want it checking all your navigation, so I’d suggest giving the specific subnav list a unique id (e.g., id=”styleswitch” or something), and then edit the jQuery to look for that instead (e.g., $(“#styleswitch li a”)).

    Also, you’ll need to specify one of the optional CSS files as your default. Just specify it in the head like you normally would. When the user makes a different selection (or if they have a different CSS file saved as their default), the page will switch over to their style as soon as it loads.

    Hope that helps!

  9. On May 05, 2009
    2:42PM

    jefferis peterson said:

    Hi, thanks for the help. Yes it works now but it will not work with the current navigation structure I have. I tried adding the id simply to the href but that will not work. I had to create an enclosing div ID on thesubmenu li, which messes up the rest of the nav structure. It works but looks like dirt… and it is non compliant. So, I’ll have to create a separate menu… but it does work. Thanks for the help. I guess I couldn’t tell from the code and your description that the $nav was a generic default… :-)

  10. On June 09, 2009
    3:50AM

    Ramil said:

    Thanks for the great tutorial.

    I have a problem though. It will not work with @import on CSS, at least for me. I have two CSS file, style.css and style1.css. On style1.css, I just use @import url(“style.css”); and some classes that will change when it switches. If I switch to style1.css, no CSS applied to the my HTML document. Any ideas?

  11. On June 09, 2009
    8:26AM

    Rob Glazebrook said:

    Hi Ramil,

    My best suggestion when trying to use the @import command is, if you’re calling a stylesheet from inside another stylesheet, make sure the @import line is the very first line in your document. That line has to come first, before any CSS rules, any comments… anything at all.

    Good luck!

  12. On June 20, 2009
    12:12PM

    ZK@Web Marketing Blog said:

    It looks good but has a catch.
    Every time you open an article page you will be in fact loading two pages(article.php and comment_new.php).
    It does not include comment_new.php, it renders it, blocks, theme, everything.

    If you looking for performance then this hack is not a solution.

  13. Andy Beattie said:

    Thank you very much for sharing your code. I have been looking at many solutions and yours is definately one of the best quality and the most thorough I have come across with very little in the way of limitation. I say this because of the cookie memory feature, as well as less requests and overhead than many of the solutions that require the page to load all stylesheets at once (check out the old ALA method with rel=”alternate”, it’s not as clean as yours nor as efficient). Who wants to drag those css files into the cache when they have not been requested? Certainly not me when I am trying to develop an efficient online application that loads as fast as possible.

    I made a slight modification in how I set up the framework, and this was to remove all colours from the base.css and to provide a default colour css file. Thus there are two style links in the head consisting of one large base.css with all formatting etc but no colour values, and then a couple of very small css files that feature only the selector names that I want to change colour.

    And for the ul nav links, I simply got rid of the text in the href links and made the colour an actual indicator like:

    .yellow { width:16px; height:16px; background:#FFCC00; text-decoration:none; display:inline-block;}
    .blue {width:16px; height:16px;background:#6694E3; text-decoration:none; display:inline-block;}
    .green {width:16px; height:16px;background: #728B2E; text-decoration:none; display:inline-block;}



    This looks great and neat on the page and is very intuitive to the user.

    Once again Rob, thank you so much for the help, although I am an old css dog, having been in the game for about 8 years now, you have saved me many many hours. I look forward to reading more of your quality posts and sharing code with you in the future.

    Best Wishes!

  14. anonymousprogrammer said:

    THANK YOU!

    I was looking for a great way to swap stylesheets without loading them all initially in the head, and I never knew you could put a class on a element. Solves the problem perfectly!

  15. IT Support Glasgow said:

    This is a very intresting jquery stylesheet switcher.

    Giving little functions like this on your website or blog may bring users back.

  16. Rowan said:

    I have used the jquery styleswitcher to swap the css, BUT the style.css, which is the standard style (in wordpress) over-rides the over styles. I can modify the standard css so the new styles will apply the desired affect, but then the standard css, which will be seen first is stripped down and not at all the design! Help!

    Thanks, Rowan

  17. On May 06, 2010
    5:15PM

    olivier said:

    Thank you.
    Unfortunately this isn’t working for me.

    Could it be because I have ids in my anchors?

    red
    yellow

    If not, how to debug it?
    I’ve tried to put some ‘alert’ but nothing is poping up.
    And it looks like the cookie isn’t written either !

  18. On June 24, 2010
    6:06AM

    ULLASMOHAN said:

    Jquery is amazing..
    Thankz for ur Tutorial

  19. On July 21, 2010
    5:39PM

    RobbyDesigns said:

    Great and simple article, nicely worded. I’m a designer more than a Dev but I am learning jquery so I know what’s possible and appreciate a good article well written, nice work.
    Kudos to you!

  20. On August 18, 2010
    11:48AM

    Aman said:

    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

  21. Ant said:

    Good work. :)

    I seem to have a problem though. Everything works fine when I navigate to pages within the root of the site – the chosen css is retained. However, if I navigate to a page that’s within a folder in the root, the CSS is not loaded because it is looking for the CSS file from within that folder.

    e.g.

    Navigating around the root, from inspecting the DOM, the path is:
    mySite/assets/myStyle.css

    Navigating to a folder within the root, it’s looking for the CSS from within that folder. Looking at the DOM, the path is:
    mySite/newFolder/assets/myStyle.css

    Is there a way to solve this?

    Thanks a lot for any help. :)

    Cheers

  22. Rob Glazebrook said:

    Hi Ant,

    The simplest solution would be to use absolute paths for your CSS files. So instead of “mySite/assets/myStyle.css”, use “/mySite/assets/myStyle.css”. That forward slash at the beginning means “go all the way back to root,” and it works no matter how deep into your site you get.

  23. KLM said:

    I’m wondering, is it possible to call a style sheet based on a parameter in a querystring rather than an href? Basically… if somesite.com?style=Larger then call that style sheet. I want to include the stylesheet parameter from an external link. THANKS!

  24. TheFallenAngel said:

    Hi,
    Your tutorial is fairly good you explain it really well however I feel like there is something missing and thats the bit where you actually tell us where to put the HTML coding in our already made HTML coding I know where to put the links but I am not sure after that.

  25. Printing Glasgow said:

    This is a very interesting jquery stylesheet switcher.

    Giving little functions like this on your website or blog may bring users back.

  26. Kenneth Odle said:

    This is very close to what I am looking for, but is there a way to put the links into a drop-down menu? Thanks!

  27. Adam said:

    I’m trying to us this to load a theme css file while keeping my main css file loaded.

    The main css structure of my site and consists of a file containing about 1000 lines that I want to say loaded all the time.

    Then I’ve created a couple of themes css files that just change the sites colors, these files are each about 40 line each.

    Now I’m trying to implement this stylesheet switcher but every time I try it, it just unloads my main css file and activates one of the themes.

    How can I go about having one main css file that doesn’t change and have this switch only effect my theme files?

    thanks

  28. Preston said:

    Hey, nice tutorial. But I have no problem. I’m using two stylesheets on the page (base.css and red.css) / OK?

    I want to change the red.css for blue.css but preserving base.css on page.

    How do I do this?

  29. Kelly @ Alphabetix said:

    Of course this tutorial is so awesomely simple, and blows away my “Cookie” mind hole. Thanks for sharing!

  30. Matt said:

    Hey Rob – Great tutorial – I am having the same problem as a couple other commenters. I need to have multiple stylesheets active at the same time. Your tutorial turns all stylesheets except the selected off. Do you have a solution for this? Thanks again

  31. On March 23, 2011
    4:30PM

    Alyssa said:

    Rob,

    This is amazing. It works like a charm. The only thing is, it works when I’m playing around with it locally, but once I bring it live on the server, it doesn’t work. Do you have any solutions?

  32. On April 14, 2011
    9:54AM

    Andy said:

    Thanks Rob, saved me a load of time with this css switcher!

  33. On April 28, 2011
    4:05PM

    damian said:

    thank u …it is realy cool…one question….if u dont mind…what should i do if i want one button to switch between two styles….

  34. On May 18, 2011
    1:32PM

    Haydur said:

    For Matt and others who are having trouble with this script affecting multiple stylesheets on the same document:

    You can limit the application of stylesheet switch by using JQuery selectors. For example, if you only want sheets with the common name “main” in them, i.e. “main1.css” and “main_blue.css”, you should change $(“link”).attr(“href”,$.cookie(“css”)); to $(‘link[href*="main"]‘).attr(“href”,$(this).attr(‘rel’));

    You can also add custom attribute to your stylesheet tag and change the selector to something like $(‘link[custom_attribute="attribute_val"]‘)

  35. On June 22, 2011
    6:50PM

    fabricio said:

    great work!

  36. elizabeth said:

    Hey, Don’t know what I am doing, but need your help to use this code to change my style sheets.. Any Ideas??

    Thanks a Million..

  37. Bob Mazzo said:

    Great article and very helpful more than two years later !

    I experimented with using a dropdown list instead of list, and here’s what I came up with (yes I got it working):

    My Html inside a :

    ui-lightness
    redmond
    vader
    ui-lightness

    My Javascript function with some jQuery:

    function changeTheme() {
    var selectedVal = $(“select option:selected”).val();
    var selectedTxt = $(“select option:selected”).text();
    $(“link”).attr(“href”, selectedVal);
    return false;
    }

    Sorry I couldn’t format the code properly here…

    thanks Rob!

    Sincerely,
    Bob Mazzo

  38. Bob Mazzo said:

    Sorry but I noticed my html didn’t show up in my previous post:

    ui-lightness
    redmond
    vader
    ui-lightness

  39. Shyanaka said:

    Thanks dude. Was really helpful. Saved lot of time.

  40. pete said:

    Great little tutorial.

    Was just wondering if there was a way of fading between the different stylesheets?

    Cheers
    Pete

17 Responses Elsewhere

  1. On April 04, 2009
    12:21AM

    sodevious.net; design and resource blog » Blog Archive » RSS Link Love! said:

    [...] 1. CSS Newbie shows us how to create a Simple jQuery Stylesheet Switcher. [...]

  2. A Simple jQuery Stylesheet Switcher said:

    [...] Visit Source. [...]

  3. 網站製作學習誌 » [Web] 連結分享 said:

    [...] A Simple jQuery Stylesheet Switcher [...]

  4. On May 07, 2009
    9:20PM

    Daily Digest for 20090508 - lifestream@add said:

    [...] A Simple jQuery Stylesheet Switcher [...]

  5. Create a better jQuery stylesheet switcher - Programming Blog said:

    [...] 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. [...]

  6. Dynamic Stylesheet switching « 0510ML said:

    [...] I've recently been in need of a function that dynamically were able to switch stylesheets without reloading the page. After a lot of searching, I found a post by Rob Glazebrook. [...]

  7. Adriano Meira » Trocando CSS e gravando em cookies com jQuery (Stylesheet Switcher) said:

    [...] deste artigo vão para CSS newbie. Valeu [...]

  8. On May 06, 2010
    4:14PM

    10 Practical Jquery Style Switchers said:

    [...] 8. A Simple jQuery Stylesheet Switcher [...]

  9. ThemeSwitcher in Web Design, Fantstic Examples and Tutorials | Design Reviver said:

    [...] A Simple jQuery Stylesheet Switcher [...]

  10. Pattern Inc » ThemeSwitcher in Web Design, Fantstic Examples and Tutorials said:

    [...] A Simple jQuery Stylesheet Switcher [...]

  11. On June 07, 2010
    12:22PM

    ThemeSwitcher in Web Design, Fantstic Examples and Tutorials said:

    [...] A Simple jQuery Stylesheet Switcher [...]

  12. Anonymous said:

    [...] [...]

  13. PHP style sheet switcher (with cookies) | JP.com said:

    [...] users to switch stylesheets, you can do it all clientside with JavaScript for instance (with jquery for instance). This wasn’t practical in my circumstances though, as keeping HTTP requests to [...]

  14. On July 21, 2011
    12:23AM

    links for 2011-07-20 | axelintu : links said:

    [...] A Simple jQuery Stylesheet Switcher (tags: css jquery design tutorial useful good reverse-ingeniering) This entry was posted in Links by axelintu. Bookmark the permalink. LikeBe the first to like this post. [...]

  15. Añadiendo JQuery « Guías astronómicas said:

    [...] conmutador de estilos se basa en el de CSSNewbie, pero con la diferencia de que, de momento, he preferido no usar cookies, y que usaré un solo [...]

Leave a Comment