Dynamically load css stylesheet and wait for it to load

16,028

Solution 1

You need to insert a link node in the head and then attach onload event to that. In your code link is a String. See sample code below on how to implement what you want.

var link = document.createElement('link');
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.onload = CSSDone;
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

Solution 2

You can try this i believe.. include the CSSDone() code in $("head").append(link)'s callback

$(document).ready(function(){
$('.btn').on('click', function(){
link = "<link class='listcss' rel='stylesheet' href='/list.css'>";
        $("head").append(link, function(){
        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");       
            }

        }); // append link

        }); // button click
}); // document ready

Solution 3

Using jQuery:

var head = $('head');
var link = $('<link>')
    .attr('rel', 'stylesheet')
    .attr('type', 'text/css')
    .attr('href', url)
                        .on('load', callback)
                        .on('error', error)
                       .appendTo(head);

Share:
16,028
mesqueeb
Author by

mesqueeb

I really try to enjoy life. And I try to always be sunshine. Positive and not overthink things. I succeed usually at being positive, but fail at not overthinking things. :) I found that I like the following things: Photography (people mostly) Teaching (anything) Learning (about programming &amp; technology) Making lists State management (in general, I know it's weird...) Films Comedy Love I'm currently into creating front-end only SPA, PWA, SSR with JavaScript and Vue.js!! I also make iOS and android apps like CineMatch.

Updated on July 22, 2022

Comments

  • mesqueeb
    mesqueeb almost 2 years

    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.

  • YugoAmaryl
    YugoAmaryl over 5 years
    @mesqueeb, I don' think it will work, I don't think link has an onload event
  • mesqueeb
    mesqueeb over 5 years
    @mok ah well. I can’t remember this anyway. It’s been more than two years XD
  • YugoAmaryl
    YugoAmaryl over 5 years
    I end up using a hack, with the Image.onerror event
  • I wrestled a bear once.
    I wrestled a bear once. almost 5 years
    link.onload = CSSDone ....there is no reason to have an anonymous function that doesn't nothing but call another function.