jquerycssdocument-ready

Dynamically load css stylesheet and wait for it to load


I have a script that detects a button click on which it will attach a CSS stylesheet to the "head" with jQuery like so:

const link = "<link class='listcss' rel='stylesheet' href='http://....list.css'>";
$("head").append(link);

Then I need to do some calculations based on the css width and height properties:

function CSSDone(){
            if($(window).width()>640){
                $(".grid-item").css({"height":$(".grid-item").width()*0.2});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.2});
            console.log("a");
            }else{
                $(".grid-item").css({"height":$(".grid-item").width()*0.33});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.33});
            console.log("b");       
            }
        }
        CSSDone();

However, if I launch CSSDone(); right after adding the stylesheet, the calculations happen before the css is loaded. I searched the web like crazy but everything I tried doesn't work:

I tried these options:

  1. Does not work:

    link.onload = function () { CSSDone(); }

  2. Does not work:

     if (link.addEventListener) {
       link.addEventListener('load', function() {
         CSSDone();
       }, false);
     }
    
  3. Does not work:

     link.onreadystatechange = function() {
       var state = link.readyState;
       if (state === 'loaded' || state === 'complete') {
         link.onreadystatechange = null;
         CSSDone();
       }
     };
    
  4. Does not work:

     $(window).load(function () {
         CSSDone();
     });
    
  5. Does not work:

     $(window).bind("load", function() {
         CSSDone();
     });
    

Believe me. Nothing works......


**One workaround:**

I load the css in the DOM and immidiately remove it again with jQuery. That way when adding the link to the head later it's fast enough.


Solution

  • Pure JavaScript solution.

    You need to insert a link node in the head and then attach onload event to that. Onload attribute can be assigned a callback function which is executed once css file is loaded. See sample code below on how to implement what you want.

    let CSSDone = function() {....} // Callback function
    let link = document.createElement('link');
    link.setAttribute("rel", "stylesheet");
    link.setAttribute("type", "text/css");
    link.onload = CSSDone; // CSSDone is the callback function
    link.setAttribute("href", 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css');
    document.getElementsByTagName("head")[0].appendChild(link);
    

    Check jsfiddle.

    MDN reference on Link element in case you are curious