73

Is there a way to load external CSS files, like we load JS file by using .getScript method and also use the callback function like in .getScript

$("<link/>", {
   rel: "stylesheet",
   type: "text/css",
   href: "/styles/yourcss.css"
}).appendTo("head");

This Works in FireFox and similar but not in IE.

Starx
  • 77,474
  • 47
  • 185
  • 261

8 Answers8

118

In jQuery 1.4:

$("<link/>", {
   rel: "stylesheet",
   type: "text/css",
   href: "/styles/yourcss.css"
}).appendTo("head");

http://api.jquery.com/jQuery/#jQuery2

RedWolves
  • 10,379
  • 12
  • 49
  • 68
  • 7
    Ok, but how to use callback function like .getScript() once the CSS file is loaded – Starx Apr 22 '10 at 00:17
  • 1
    For me it didn't work in IE8. Here is a working solution http://stackoverflow.com/questions/805384/how-to-apply-inline-and-or-external-css-loaded-dynamically-with-jquery (by user "user406905") – Vilius Paulauskas Jan 29 '12 at 17:53
  • I have just posted how to do this with callback on another question http://stackoverflow.com/questions/3498647/jquery-loading-css-on-demand-callback-if-done/17858428#17858428 – Popnoodles Jul 25 '13 at 12:48
  • 2
    This looks to be an exact copy and paste of the code in the question, the question was asking if there is a equivalent to [jQuery.getScript()](http://api.jquery.com/jQuery.getScript/) to which the answer is `no`. – Luke T O'Brien Mar 20 '18 at 11:39
22

Quick function based on responses.

loadCSS = function(href) {

  var cssLink = $("<link>");
  $("head").append(cssLink); //IE hack: append before setting href

  cssLink.attr({
    rel:  "stylesheet",
    type: "text/css",
    href: href
  });

};

Usage:

loadCSS("/css/file.css");
xgMz
  • 3,334
  • 2
  • 30
  • 23
  • Thank you... I combined your code with MVC 4 bundles and it worked! – Tom Jun 19 '13 at 12:08
  • See my answer for added callback, without triggering additional request on the CSS resource. I don't think this IE hack is relevant in 2019. – Willster Aug 15 '19 at 11:07
18
$("head").append("<link>");
var css = $("head").children(":last");
css.attr({
      rel:  "stylesheet",
      type: "text/css",
      href: "address_of_your_css"
});
Raul Agrait
  • 5,938
  • 6
  • 49
  • 72
  • Ok, but how to use callback function like .getScript() once the CSS file is loaded – Starx Apr 22 '10 at 00:15
  • 1
    @Starx Please edit your original question to reflect exactly what you need - not only the loading of external CSS files dynamically, but also a callback. – Raul Agrait Apr 22 '10 at 17:17
  • Yay for IE hacks. You second line could be: `var css = $('head > :last')` yes? – Julian Jun 28 '12 at 04:38
  • I've adapted this script to be used with jquery 1.12.4 without any problems, FYI. – j4v1 Jul 31 '16 at 21:58
  • 4
    Will be easier and more intuitive to use appendTo, like this: `$("").attr({ rel: "stylesheet", type: "text/css", href: "address_of_your_css" }).appendTo("head");` – oriadam May 13 '17 at 22:06
10

I think what the OP wanted to do was to load a style sheet asynchronously and add it. This works for me in Chrome 22, FF 16 and IE 8 for sets of CSS rules stored as text:

$.ajax({
    url: href,
    dataType: 'text',
    success: function(data) {
        $('<style type="text/css">\n' + data + '</style>').appendTo("head");                    
    }                  
});

In my case, I also sometimes want the loaded CSS to replace CSS that was previously loaded this way. To do that, I put a comment at the beginning, say "/* Flag this ID=102 */", and then I can do this:

// Remove old style
$("head").children().each(function(index, ele) {
    if (ele.innerHTML && ele.innerHTML.substring(0, 30).match(/\/\* Flag this ID=102 \*\//)) {
        $(ele).remove();
        return false;    // Stop iterating since we removed something
    }
});
Ed Bayiates
  • 11,060
  • 4
  • 43
  • 62
  • By downloading the external resource (css) as text and dumping it inside – Abdulhameed Jan 18 '20 at 19:23
  • @AbdulhameedShalabi as Willster explains below, css can still be cached even if it is fetched over ajax. It depends on the original response headers of the resource. – Ed Bayiates Jan 27 '20 at 21:12
4

    //load css first, then print <link> to header, and execute callback
    //just set var href above this..
    $.ajax({
          url: href,
          dataType: 'css',
          success: function(){                  
                $('<link rel="stylesheet" type="text/css" href="'+href+'" />').appendTo("head");
                //your callback
            }
    });

For Jquery 1.2.6 and above ( omitting the fancy attributes functions above ).

I am doing it this way because I think that this will ensure that your requested stylesheet is loaded by ajax before you try to stick it into the head. Therefore, the callback is executed after the stylesheet is ready.

tmsimont
  • 2,651
  • 2
  • 25
  • 36
  • 1
    There is no support for this in jQuery (dataType: 'css'), does it work for you? – jayarjo Oct 10 '12 at 19:30
  • interesting.. yes it does work for me. I suppose this answer would be more correct without the dataType parameter, I'm not sure why that doesn't cause an error for me. (see related thread about using css dataType: http://bugs.jquery.com/ticket/10082) – tmsimont Oct 11 '12 at 00:02
  • Not efficient, you downloaded the css file but you didn't make use of the downloaded bytes in the "success" callback and then you added the tag. – Abdulhameed Jan 18 '20 at 19:29
2

Here is a function that will load CSS files with a success or failure callback. The failure callback will be called just once, if one or more resources fail to load. I think this approach is better than some of the other solutions because inserting a element into the DOM with an HREF causes an additional browser request (albeit, the request will likely come from cache, depending on response headers).

function loadCssFiles(urls, successCallback, failureCallback) {

    $.when.apply($,
        $.map(urls, function(url) {
            return $.get(url, function(css) {
                $("<style>" + css + "</style>").appendTo("head");
            });
        })
    ).then(function() {
        if (typeof successCallback === 'function') successCallback();
    }).fail(function() {
        if (typeof failureCallback === 'function') failureCallback();
    });

}

Usage as so:

loadCssFiles(["https://test.com/style1.css", "https://test.com/style2.css",],
    function() {
    alert("All resources loaded");
}, function() {
    alert("One or more resources failed to load");
});

Here is another function that will load both CSS and javascript files:

function loadJavascriptAndCssFiles(urls, successCallback, failureCallback) {

    $.when.apply($,
        $.map(urls, function(url) {
            if(url.endsWith(".css")) {
                return $.get(url, function(css) {
                    $("<style>" + css + "</style>").appendTo("head");
                });
            } else {
                return $.getScript(url);
            }
        })
    ).then(function() {
        if (typeof successCallback === 'function') successCallback();
    }).fail(function() {
        if (typeof failureCallback === 'function') failureCallback();
    });

}
Willster
  • 2,526
  • 1
  • 32
  • 32
  • Note a negative of this solution, if you are using relative source maps, it won't be found if the css is inlined (as opposed to added via a tag). – Willster Aug 20 '19 at 10:21
  • By downloading the external resource (css) as text and dumping it inside – Abdulhameed Jan 18 '20 at 19:32
  • @AbdulhameedShalabi no, css can still be cached even if it is fetched over ajax. It depends on the original response headers of the resource. – Willster Jan 21 '20 at 13:47
0

Based on your comment under @Raul's answer, I can think of two ways to include a callback:

  1. Have getScript call the file that loads the css.
  2. Load the contents of the css file with AJAX, and append to <style>. Your callback would be the callback from $.get or whatever you use to load the css file contents.
abalter
  • 9,663
  • 17
  • 90
  • 145
-5

$("#pageCSS").attr('href', './css/new_css.css');