A Simple jQuery Stylesheet Switcher

Published April 2, 2009 by Rob Glazebrook.

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:

<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:

$(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:

$("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:

$(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:

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:

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

93 Responses

  1. Bob Mazzo (reply)

    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

  2. Pingback: 10 Simple and Easy jQuery Style Switchers | jQuery4u

  3. francis (reply)

    Hello, i seem to be having probelms with the styles stored in the cookie being reloaded.

    this is the script implemented

    $(document).ready(function() {
    $(“div.left div#wrap ul#nav li a”).click(function() {

    if($.cookie(“css”)) {
    $(“link:last”).attr(“href”,$.cookie(“css”));
    }
    $(“link:last”).attr(“href”,$(this).attr(‘rel’));
    $.cookie(“css”,$(“link:last”).attr(‘rel’), {expires: 365, path: ‘/’});
    return false;
    });
    });

    it changes the styles but will not load the stored cookie on page reload

  4. francis (reply)

    Hello,
    I edited the comment above
    i seem to be having probelms with the styles stored in the cookie not being reloaded.

    this is the script implemented

    $(document).ready(function() {
    $(“div.left div#wrap ul#nav li a”).click(function() {

    if($.cookie(“css”)) {
    $(“link:last”).attr(“href”,$.cookie(“css”));
    }
    $(“link:last”).attr(“href”,$(this).attr(‘rel’));
    $.cookie(“css”,$(“link:last”).attr(‘rel’), {expires: 365, path: ‘/’});
    return false;
    });
    });

    it changes the styles but will not load the stored cookie on page reload

  5. Pingback: WordPress Premium Theme – Big Picture Premium WordPress Theme | Make Money Online in SG

  6. Pingback: Changing the stylesheet | Open Cart Know How

  7. soulgriever (reply)

    Hi I love this plugin however when I switch style sheets (no matter which style sheet) It messes up the rest of the jquery on my page I have an html5 video and a jquery gallery and when the style changes it messes both up

  8. Joe Johnston (reply)

    #BadAss WAY better than all that other rigamaroo I have seen. Its easy to forget that jQuery is built from js and not the other way around. Forest for the trees…

    Thanks.

  9. Pingback: Ajuda mudar css

  10. Jesse (reply)

    Hey,

    Incoporated this into my website. However whenever I change stylesheets, the text becomes much thicker… even though the stylesheet I’m changing to is actually an exact replica of the first! So strange…

    1. Shawn (reply)

      @Jesse, I’m having the same problem with fonts acting crazy. Can you elaborate on what the issue was and how you fixed it? I’ve hit a wall.

      Thanks!

  11. Pingback: Prototype Process and Tools | Clarify Solutions | Dovetail Software

  12. Pingback: Prototype Process and Tools » Clarify Solutions | Dovetail Software

  13. David Pearson (reply)

    Excellent stuff, exactly what i needed.

    I have 3 font size links Is there a way to check which link is loaded against the rel of each one and then add an active class to it?

  14. David Pearson (reply)

    Managed to do it, for anyone who wants a similar thing:

    $(document).ready(function () {
    $(‘#text-size a[rel="' + $('link.fontsize').attr('href') + '"]‘).closest(‘li’).addClass(‘active’);
    });

  15. Pingback: Style Switchers for Accessibility | blog.iopan.co.ukblog.iopan.co.uk

  16. Pingback: jQuery Change CSS File Dynamically | jQuery4U | No.1 Resource for jQuery Developers

  17. www (reply)

    Hi there everyone, it’s my first pay a quick visit at this website, and piece of writing is
    truly fruitful designed for me, keep up posting
    such content.

  18. Johnf502 (reply)

    I really like your blog.. very nice colors &amp theme. Did you make this website yourself or did you hire someone to do it for you? Plz respond as I’m looking to construct my own blog and would like to know where u got this from. thank you eebadedaddde

  19. John (reply)

    This works great, except it changes the link to ALL of my stylesheets. How can I target just a single tag instead of all of them?

    1. David (reply)

      Hey John,
      any chance you could share the code with us? I’m experiencing the same problem. Would be super helpful. Thanks

  20. electronic cigarette (reply)

    E-cigarette companies have sites that publish e cigarette reviews that
    will let you know that there’s no second hand
    smoke in these devices. Use it will a nicotine patch to fight the addiction head on. 5-inch all-weather outdoor LCD TV
    is a definitely a must-have gadget for every outdoor adventurer who doesn’t
    want to miss his or her favorite TV programs.

  21. laina (reply)

    What’s up, this weekend is pleasant in support of me, since this
    point in time i am reading this fantastic educational piece of writing here at my residence.

  22. konjak superkuitu (reply)

    Heya this is kinda of off topic but I was wanting to
    know if blogs use WYSIWYG editors or if you have to manually code with HTML.
    I’m starting a blog soon but have no coding experience so I wanted to get advice from someone with experience.
    Any help would be greatly appreciated!

  23. konjak superkuitu (reply)

    Have you ever thought about publishing an ebook or guest authoring on other sites?

    I have a blog centered on the same topics you discuss and would
    really like to have you share some stories/information. I know my readers would
    value your work. If you are even remotely interested, feel free to send me an e-mail.

  24. konjak superkuitu (reply)

    An impressive share! I’ve just forwarded this onto a coworker who had been doing a little research on this.
    And he actually ordered me lunch simply because I found it for him…
    lol. So let me reword this…. Thanks for the meal!!
    But yeah, thanx for spending the time to talk about
    this issue here on your site.

  25. Gudrun (reply)

    Howdy I am so glad I found your web site, I really found you by error,
    while I was browsing on Digg for something else, Anyhow I am here now and would just like to say thanks for a
    tremendous post and a all round exciting blog
    (I also love the theme/design), I don’t have time to browse it all at the moment but I have bookmarked it
    and also added in your RSS feeds, so when I have time I will be
    back to read a great deal more, Please do keep
    up the superb work.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>