Applying stylesheets dynamically with jQuery

jquery logoA colleague of mine asked me how to apply a stylesheet to a web page dynamically using jQuery and I had never done such a thing but my first thought was that is must be pretty simple. I've spent a lot of time thinking of so many things other than web et. al. so it was nice to delve into some of that stuff again. Check out the live demo

As we know stylesheets are defined in the head section of an html file like this

<html>
    <head>
        <link rel="stylesheet" href="stylesheet.css" type="text/css" />
    </head>
    <body>
    ...
</html>

Now, say that we want to apply another stylesheet dynamically after the fact, so to speak, triggered by some event. This could be a button click or some other arbitrary event that is triggered. So, what we want to do is simply insert a new <link/> element into the head section of the page DOM. This can be done in a couple of lines of jQuery:

$(document).ready(function () {
    $("a").click(function () {
        $('head').append('<link rel="stylesheet" href="style2.css" type="text/css" />');
    });
});

The key is at what time we add the link to the style sheet. The first line in the code above repeated here asserts that the DOM is ready for manipulation.

$(document).ready(function () {
    //...
});

The second part repeated here adds a click event to all hyperlinks in the page.

$("a").click(function() { //...

And the very task is performed by the last piece of code where the head element is appended with a new link element.

$('head').append('<link rel="stylesheet" href="style2.css" type="text/css" />');

Comments (14) -

  • Jonas

    9/9/2008 10:29:17 AM | Reply

    Nice example, although I would personally prefer using something like either:

    ...
    $('head > link').filter(':first').attr('href', 'something.css');
    ...


    or

    ...
    $('head > link').filter(':first').replaceWith('<link href="something.css" ... />');
    ...


    Mainly since your code just appends a new <link> element to the DOM every time the link is clicked, without regard to the old one. Of course, these examples imply that a single <link> is used, but using jQuery selectors it would be quite easy to make it a bit "smarter".

  • Rickard

    9/16/2008 7:38:39 AM | Reply

    You're right, my attempt was at a very basic level, at best. However, just as intended. I like your first solution in particular but the requirements for the demo was that I needed to apply a second style sheet dynamically. Yours is replacing the first style sheet in the page.

    I agree that jQuery selectors makes it a whole lot easier and I'm planning another post with a more 'real-like' implementation.

  • club penguin cheats

    7/9/2009 7:37:17 AM | Reply

    Mainly since your code just appends a new <link> element to the DOM every time the link is clicked, without regard to the old one. Of course, these examples imply that a single <link> is used, but using jQuery selectors it would be quite easy to make it a bit "smarter".

  • Eugene Kerner

    2/9/2014 1:07:55 AM | Reply

    Note that IE doesn't seem to like like attr() on this one ...

    // works in FF and IE ...
    $('head').append('<link rel="stylesheet" type="text/css" href="/shared/css/screen.css.php?' + screen.width + '&height=' + screen.height + '" />');

    // works in FF and IE ...
    $('<link rel="stylesheet" type="text/css" href="/shared/css/screen.css.php?' + screen.width + '&height=' + screen.height + '" />').appendTo($('head'));

    // works in FF but not IE ...
    $('<link />').attr({
    rel : 'stylesheet',
    type : 'text/css',
    href : '/shared/css/screen.css.php?width=' + screen.width + '&height=' + screen.height
    }).appendTo($('head'));

    // works in FF but not IE ...
    $('head').append(
    $(document.createElement('link')).attr({
    rel : 'stylesheet',
    type : 'text/css',
    href : '/shared/css/screen.css.php?width=' + screen.width + '&height=' + screen.height
    })
    );

    // works in FF but not IE ...
    $(document.createElement('link')).attr({
    rel : 'stylesheet',
    type : 'text/css',
    href : '/shared/css/screen.css.php?width=' + screen.width + '&height=' + screen.height
    }).appendTo(document.getElementsByTagName('head')[0]);

  • afaoiu

    2/9/2014 1:17:53 AM | Reply

    doesn't work in IE7

  • John

    2/9/2014 1:18:15 AM | Reply

    Thanks for the post. Just what I needed for my script

    • Daniel

      2/9/2014 1:18:57 AM | Reply

      That's what I looked for, I am going to try it.
      But, is there as well a way to remove the added css dynamically?

  • calvin

    2/9/2014 1:19:58 AM | Reply

    Thanks I have used this to create a default style switcher for my JQuery mobile application using localStorage and html5 ! Test it on your mobile or tablet here http://cambs.eu/mobile/

  • Poole Web Design

    2/9/2014 1:20:33 AM | Reply

    This works absolutely fine for me! But how would you also add a class to the body tag? Would you have to wrap it up in a function? Thoughts would be really appreciated!

    • Rickard

      2/9/2014 1:21:16 AM | Reply

      I would do something like:

      $("body").addClass("foo");

      You don't have to wrap it in a function but I prefer packaging much of my JavaScript code in either closure scope or in jQuery plugins. See rickardnilsson.net/.../...itching-stylesheets.aspx for more info.

  • Stan

    2/9/2014 1:21:47 AM | Reply

    Nice...used this to dynamically add a css stylesheet for when there was no css3 border-radius support...had it in the page, but the image references got too hairy since it's a facebook app http://apps.facebook.com/mytopslist (it's in an iframe) and you have to keep the image references relative so people can also access the https version...also I went to login via facebook below, but i got an error (maybe your plugin needs to be updated?)

  • vinod

    2/9/2014 1:22:07 AM | Reply

    I tricked like this , i have link tag in header instead of append used html that work in both browser's IE8 and FF
    and other way is change the link attribute href with our stylesheet name,
    $(document).ready(function() {
    $(window).resize(function() {
    var winwdith = $(window).width();
    // This will fire each time the window is resized:
    if(winwdith >= 800) {
    // if larger or equal
    //alert(winwith);
    //$('head').html('<link href="ggcss.css" rel="stylesheet" type="text/css" />');
    $('link').attr('href','ggcss.css');
    } else {
    //alert(winwith);
    // if smaller
    //$('head').html('<link href="ggmcss.css" rel="stylesheet" type="text/css" />');
    $('link').attr('href','ggmcss.css');
    }
    }).resize();
    });
    jQuery Have Fun

  • Hasse

    2/9/2014 1:23:39 AM | Reply

    Doesn't that trigger a complete rerendering of the entire page, since the head section is closed at insertion time?
    (and if yes, is there any way to avoid that, if the new sheet is only affecting a minor part of a huge page?) :-/

Loading
Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.