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 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
- listen to link.onload
- listen to link.addEventListener('load')
- listen to link.onreadystatechange
- setTimeout and check for changes in document.styleSheets
- 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
Detect style sheet load
<link>
elements haveload
anderror
events, but they are garanteed only for Chrome, Firefox and Opera. If you don't need to support IE or Safari, I think this is just enough:<link rel="stylesheet" href="some_style.css" onload="anounceReady()">
EDIT: Just tested with IE11 and IE8,
onload
is supported butonerror
isn't. I have no Mac at hand so I don't know how Safari handles them.If you are going to support browsers don't have
load
event for<link>
elements, or very old Chrome/Firefox, there is a commonly used easy dirty but working solution. Add a piece of probing rule set at the end of your CSS file, and detect the computed style of a certain probing element (usually invisible) via JavaScript.HTML:
<div id="probe"></div>
CSS:
#probe {
position: absolute;
z-index: -1000;
}JavaScript:
var probeStyle = getComputedStyle(document.getElementById('probe'));
probeStyle.zIndex; // expect "-1000" after CSS is loaded
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.
How to determine when document has loaded after loading external css
I wrote this code, what i wanted and worked for me:
window.engineLoading = {images_count:0, images_loaded_count:0, fonts_count:0, fonts_loaded_count:0 };
document.querySelector("a").onclick = function(){ // first elemnet a
var before_stylesheets_length = document.styleSheets.length;
var before_fonts_size = document.fonts.size;
document.fonts.onloadingerror = function(a){
window.engineLoading.fonts_loaded_count++;
}
document.fonts.onloading = function(a){
window.engineLoading.fonts_count++;
}
document.fonts.onloadingdone = function(a){
window.engineLoading.fonts_loaded_count++;
}
var head= document.getElementsByTagName('head')[0];
var style= document.createElement('link');
style.rel= 'stylesheet';
style.setAttribute("href","./new_style.css");
style.onload = function(){
for(i=before_stylesheets_length; i<document.styleSheets.length; i++){
var rules = document.styleSheets[i].rules;
for(q=0; q<rules.length; q++){
var styles = rules[q].style;
for(s=0; s<styles.length; s++){
console.log(styles[s]);
if((styles[s] == "background-image" || styles[s] == "background") && styles.backgroundImage.length > 0){
window.engineLoading.images_count++;
var body= document.getElementsByTagName('body')[0];
var image = document.createElement('img');
var url = styles.backgroundImage;
url = url.replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
image.src = url;
image.width = 0;
image.height = 0;
image.setAttribute("class","pace-load-style");
image.onload = function(e){
console.log(e);
window.engineLoading.images_loaded_count++;
};
image.onerror = function(e){
window.engineLoading.images_laoded_count++;
}
body.appendChild(image);
break;
}
}
}
}
};
style.onerror = function(){};
head.appendChild(style);
setTimeout(function(){
checkCurrentState();
}, 1000);
return false;
};
function checkCurrentState(){
if(window.engineLoading.images_count == window.engineLoading.images_loaded_count && window.engineLoading.fonts_count == window.engineLoading.fonts_loaded_count){
console.log("loaded"); return true;
}console.log("still loading...");
return setTimeout(function(){
checkCurrentState();
}, 1000);
};
UPDATE: Scipt has bug on localfile because of empty rule. CSSRules is empty I don't worry about it , and no need fix it.
UPDATE: Mozilla Firefox hasnt reference document.fonts.
Detect when css is applied
Never tried before, but what about Stylesheet load events? In case IE won't fired the onload
event, and you need to support it, onreadystatechange
should works.
Detecting when CSS file is completed switch
I settled on adding an incrementing number after the id of the style tag, when I switch the style, I add the new stylesheet and remove the old one, then check with the new number to see if it has been loaded.
function switchTemplate(stylePath){
var osid = $('[id^="themeStyle-"]');
var stylenum = osid[0].id.split('-')[1];
var newstylenum = (Number(stylenum) + 1).toString();
var ns = $('<link>', {
href: stylePath,
id: 'themeStyle-' + newstylenum,
type: 'text/css',
rel: 'stylesheet'
});
$("head").append(ns);
$('#themeStyle-' + stylenum).remove();
_cssIsLoaded(ns.get(0), stylePath);
}
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();
Is browser fully loaded check
Not directly in java, since it is probably not running in the browser, but you can do it with javascript
<html>
<head>
<title>Test Page</title>
<script type="text/javascript">var myFunc = function() {
alert("The page is fully loaded!");
};
window.onload = myFunc;
</script>
</head>
Related Topics
Uncaught Typeerror: Cannot Read Property 'Classname' of Undefined
JavaScript Invalidcharactererror When Modifying a CSS Name with a Space
How to Detect State of CSS Transition via Js and Skip It
Bootstrap 4 Input Field in Popover
Does Animating the Value of a CSS3 Transform with JavaScript Rule Out Hardware Acceleration
Pause/Resume CSS Animations When Switching Tabs
Highlight Multiple Items on Hover's Condition
Run JavaScript Code in Webview
Horizontal Swipe Slider with Jquery and Touch Devices Support
Make the Change of "Active" Class in the Menu More Reliable When Scrolling
How to Let a Div Stick to Cursor
Detecting Width: Auto in Jquery
Highlight an Individual Word Within a Text Block on Hover
Using Class with Angular VS Ng-Class While Using a Mixed Expression