Dynamic loading of CSS, with callback function

A single page in a web application can be extremely complex, and pack a stack of functionality. However, much of this functionality is perhaps not needed by all visitors - and almost certainly not as part of the initial page load.

For example, you might have a page that lists a grid of database records. An "Add" button on the page will allow a visitor to add a new record. Traditionally, this would have led the visitor to a new page, where they'd have filled in the form and hit "Submit".

However, today this is more likely to leave the visitor on the current page, and use JavaScript to present some kind of pop-over form or dialog window. Styling and managing these dialogs/forms will almost always require extra CSS and JavaScript.

You could load all this extra JavaScript and CSS for every visitor to the page. However, for visitors that won't be clicking on your "Add" button, this is just a waste of time and bandwidth. In my book, quicker page load times equals a better user experience.

For loading JavaScript dynamically, jQuery provides functions with a callback event.  So you can load the JavaScript library, and then execute further code once the load process has completed.

However, it seemed that there wasn't a complimentary function for loading CSS dynamically - or at least, not with a callback event.

I had a think about how you might best manage this process, and here's what seems to work -

  1. Download the Url using an XMLHttpRequest (jQuery's $.ajax function)
  2. When the success callback event is triggered, add a <link> tag to the <head> of the page, referencing the same Url.

The first step downloads the file and adds it to the browser's cache,  The second step adds a reference to the stylesheet to the top of the page.

If we examine the network debug window in Microsoft Edge, you can see this process at work:






As you can see, the first request for the file (an XMLHttpRequest) loads the stylesheet from the server.

The second (normal) request loads the same file from the browser cache.

Anyway, I wrapped this code in to a small jQuery plugin:

 (function ($)  
 {  
   $.loadCSS = function (options) {  
     var settings = $.extend({  
       url: "", callBack: null  
     }, options);  
     if(settings.Url!="")  
     {  
       // check that the stylesheet hasn't already been added  
       if ($("link[href='" + settings.url + "']").length == 0) {   
         $.ajax({  
           url: settings.url, type: "get",  
           cache: true, accepts: { css: "text/css" },  
           converters: {  
             "text css": function (result) {  
               return result; // no conversion required  
             }  
           }, dataType: "css",  
           success: function (data) {  
             var cssLink = $("<link>");  
             $("head").append(cssLink);  
             cssLink.attr({  
               rel: "stylesheet",  
               type: "text/css",  
               href: settings.url  
             });  
             if (settings.callBack != null) {  
               setTimeout(function () { settings.callBack(); }, 50);  
             }  
           }, error: function (xhr, ajaxOptions, thrownError) {  
             console.log(thrownError);  
           }  
         });  
       }  
       else  
       {  
         if (settings.callBack != null) {  
           settings.callBack();  
         }  
       }  
     }  
   };  
 }(jQuery));  

... which you call like this -

 $.loadCSS({ url: "/css/mycss.min.css", callBack: function () { alert("CSS loaded"); } });  

It works on Chrome, Edge and Internet Explorer as far back as version 7.

Any feedback would be welcome.

Comments