How to Check If All CSS Files Have Been Downloaded to Insert HTML Using JavaScript

How to check if all CSS files have been downloaded to insert HTML using JavaScript?

You could use YepNope.js, YepNope allows you to build asynchronous conditional tests to see whether resources have loaded. Once your tests have passed you can tell it to inject new CSS or JS files.

Example below has been taken from the YepNope.js site.

yepnope.injectCss( stylesheetSource [, callback ] [, elemAttributes ] [, timeout ]);

// Example
yepnope.injectCss("print.css", function () {
console.log("css injected!");
}, {
media: "print"
}, 5000);

You can even make YepNope load the initial CSS files first and then once they have completed loading YepNope can trigger a callback to do additional tasks, such as loading more JS or CSS files.

Is there any way to detect when a CSS file has been fully loaded?

edit: It should be noted that browser support for onload events on CSS files has improved since my original answer. It is not fully supported though, so my answer below still has some relevance. Here is a compatibility chart, not sure how legit the source is though.

Ok, I finally found a solution.

This guy http://tugll.tugraz.at/96784/weblog/9080.html inserts link-tags and polls document.styleSheets[index].rules until it is no longer undefined (where index of course is the index of the newly inserted file). Unfortunately his code is buggy and only works with Safari & FF. So I fixed the bugs, added functionality for Opera and Internet Explorer and even added features for adding multiple CSS and JS files and 1 final callback (when all files are loaded) in a sweet and simple lazyloader-function. The result can be found here:

https://github.com/LukasBombach/Lazyloader

HOW TO check if an external (cross-domain) CSS file is loaded using Javascript

This is actually what I did.

To ensure a specific CSS file is loaded, I added a style in the end of the CSS file. For example:

#ensure-cssload-8473649 {
display: none
}

Now I have a JavaScript function which will fire the callback specified when the above style is loaded on the page:

var onCssLoad = function (options, callback) {
var body = $("body");
var div = document.createElement(constants.TAG_DIV);
for (var key in options) {
if (options.hasOwnProperty(key)) {
if (key.toLowerCase() === "css") {
continue;
}
div[key] = options[key];
}
}

var css = options.css;
if (css) {
body.appendChild(div);
var handle = -1;
handle = window.setInterval(function () {
var match = true;
for (var key in css) {
if (css.hasOwnProperty(key)) {
match = match && utils.getStyle(div, key) === css[key];
}
}

if (match === true) {
window.clearTimeout(handle);
body.removeChild(div);
callback();
}
}, 100);
}
}

And this is how I used the function above:

onCssLoad({
"id": "ensure-cssload-8473649",
css: {
display: "none"
}
}, function () {
// code when you want to execute
// after your CSS file is loaded
});

Here the 1st parameter takes the options where id is to check against the test style and css property to verify against what loaded from the CSS.

How to determine if CSS has been loaded?

After doing some research and writing up my answer, I stumbled upon this link that explains everything you need to know about CSS, when it is loaded and how you can check for it.

The link provided explains it so well, in fact, that I'm adding some quotes from it for future reference.

If you're curious, my answer was going to be #2 and a variation of #4.

When is a stylesheet really loaded?

...

With that out of the way, let's see what we have here.

// my callback function 
// which relies on CSS being loaded function
CSSDone() {
alert('zOMG, CSS is done');
};

// load me some stylesheet
var url = "http://tools.w3clubs.com/pagr/1.sleep-1.css",
head = document.getElementsByTagName('head')[0],
link = document.createElement('link');

link.type = "text/css";
link.rel = "stylesheet";
link.href = url;

// MAGIC
// call CSSDone() when CSS arrives
head.appendChild(link);

Options for the magic part, sorted from nice-and-easy to ridiculous

  1. listen to link.onload
  2. listen to link.addEventListener('load')
  3. listen to link.onreadystatechange
  4. setTimeout and check for changes in document.styleSheets
  5. setTimeout and check for changes in the styling of a specific element you create but style with the new CSS

5th option is too crazy and assumes you have control over the content of the CSS, so forget it. Plus it checks for current styles in a timeout meaning it will flush the reflow queue and can be potentially slow. The slower the CSS to arrive, the more reflows. So, really, forget it.

So how about implementing the magic?

// MAGIC 

// #1
link.onload = function () {
CSSDone('onload listener');
};

// #2
if (link.addEventListener) {
link.addEventListener('load', function() {
CSSDone("DOM's load event");
}, false);
};

// #3
link.onreadystatechange = function() {
var state = link.readyState;
if (state === 'loaded' || state === 'complete') {
link.onreadystatechange = null;
CSSDone("onreadystatechange");
}
};

// #4
var cssnum = document.styleSheets.length;
var ti = setInterval(function() {
if (document.styleSheets.length > cssnum) {
// needs more work when you load a bunch of CSS files quickly
// e.g. loop from cssnum to the new length, looking
// for the document.styleSheets[n].href === url
// ...

// FF changes the length prematurely :(
CSSDone('listening to styleSheets.length change');
clearInterval(ti);
}
}, 10);

// MAGIC ends

Which file downloads first? css or js

In general… <script> elements that are not defer or async can document.write so block futher parsing of the HTML document. The <link> will not be added to the DOM before the script has been processed so it won't download the CSS until then.

However, HTTP 2 is arriving, which allows the server to start delivering associated resources without the browser explicitly requesting them.

How to use Javascript to check and load CSS if not loaded?

Just check to see if a <link> element exists with the href attribute set to your CSS file's URL:

if (!$("link[href='/path/to.css']").length)
$('<link href="/path/to.css" rel="stylesheet">').appendTo("head");

The plain ol' JS method is simple too, using the document.styleSheets collection:

function loadCSSIfNotAlreadyLoadedForSomeReason () {
var ss = document.styleSheets;
for (var i = 0, max = ss.length; i < max; i++) {
if (ss[i].href == "/path/to.css")
return;
}
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = "/path/to.css";

document.getElementsByTagName("head")[0].appendChild(link);
}
loadCSSIfNotAlreadyLoadedForSomeReason();

How to load all css under a folder without providing css file name

If you do not mind having multiple requests to the server, you can create a main CSS file and inside it add @import to the other files.

main.css

@import url('/css/file_one.css');
@import url('/css/file_two.css');
@import url('/css/dir/file_one.css');

And in your HTML file

<link rel="stylesheet" href="/css/main.css" />

Just do not remember if in import need to add the complete URL.



Related Topics



Leave a reply



Submit