javascript 有什么方法可以检测 CSS 文件何时已完全加载?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4488567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 13:52:03  来源:igfitidea点击:

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

javascriptcsslazy-loading

提问by Lukas

I've been testing a lot of lazy-loaders for JavaScript and CSS that insert <script> and <link> tags to load files. However the problem is, that <link>tags don't fire onloadso it's difficult to detect when they're loaded. The only workaround I found for this is to set display: none;(in the CSS file that is to be loaded) on a dummy element and poll that element to check when it has been set to display: none. But that, apart from being ugly, of course only works for a single CSS file.

我一直在为 JavaScript 和 CSS 测试很多惰性加载器,它们插入 <script> 和 <link> 标签来加载文件。然而问题是,<link>标签不会触发,onload因此很难检测到它们何时被加载。我找到的唯一解决方法是设置display: none;(在要加载的 CSS 文件中)一个虚拟元素并轮询该元素以检查它何时被设置为显示:无。但是,除了丑陋之外,当然仅适用于单个 CSS 文件。

So I was wondering; Is there any other way to detect if a CSS file has been loaded?

所以我想知道; 有没有其他方法可以检测 CSS 文件是否已加载?

采纳答案by Lukas

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.

编辑:应该注意的是,自从我的原始答案以来,浏览器对 CSS 文件上的 onload 事件的支持有所改进。虽然它没有得到完全支持,所以我下面的回答仍然有一些相关性。这是一个兼容性图表,但不确定来源是否合法。

Ok, I finally found a solution.

好的,我终于找到了解决方案。

This guy http://tugll.tugraz.at/96784/weblog/9080.htmlinserts 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:

这家伙http://tugll.tugraz.at/96784/weblog/9080.html插入链接标签并轮询 document.styleSheets[index].rules 直到它不再是未定义的(其中 index 当然是新的索引插入的文件)。不幸的是,他的代码有问题,只能与 Safari 和 FF 一起使用。所以我修复了错误,为 Opera 和 Internet Explorer 添加了功能,甚至添加了添加多个 CSS 和 JS 文件和 1 个最终回调(加载所有文件时)的功能,这些功能在一个甜美而简单的惰性加载器函数中。结果可以在这里找到:

https://github.com/LukasBombach/Lazyloader

https://github.com/LukasBombach/Lazyloader

回答by Ben

Worth knowing that nowcurrent versions of Chrome and Firefox fire the onloadevent on links.

值得一提的是,现在当前版本的 Chrome 和 Firefox 会onload在链接上触发该事件。

var cssFile = document.createElement("link");
cssFile.setAttribute("rel", "stylesheet");
cssFile.setAttribute("type", "text/css");
// Add event listener
cssFile.onload = function(){ console.log('loaded'); }
cssFile.setAttribute("href", 'pathToYour.css');
document.getElementsByTagName("head")[0].appendChild(cssFile);

回答by eriksv88

Edit:(Because of the possible not support WebKit)

编辑:(因为可能不支持WebKit)

So I'd rather recommend JQuery LOADER

所以我宁愿推荐JQuery LOADER

$("a.button, input.button, button.button").Loader(
{
    url: [
        'core.css',
        'theme.css',
        'button.css'
    ],
    success: function() {
        $(this).button();
    }
});


You can take a look at LazyLoadJavaScript library.

您可以查看LazyLoadJavaScript 库。

LazyLoad is a tiny (only 1,541 bytes minified), dependency-free JavaScript library that makes it super easy to load external JavaScript and (new in this version) CSS files on demand. It's ideal for quickly and unobtrusively loading large external scripts and stylesheets either lazily after the rest of the page has finished loading or on demand as needed.

In addition to CSS support, this version of LazyLoad also adds support for parallel loading of multiple resources in browsers that support it. To load multiple resources in parallel, simply pass an array of URLs in a single LazyLoad cal

LazyLoad 是一个很小的(仅压缩 1,541 字节)、无依赖的 JavaScript 库,它使按需加载外部 JavaScript 和(此版本中的新功能)CSS 文件变得非常容易。它非常适合在页面的其余部分完成加载后或按需按需快速且不显眼地加载大型外部脚本和样式表。

除了 CSS 支持,此版本的 LazyLoad 还增加了对支持它的浏览器中多个资源的并行加载的支持。要并行加载多个资源,只需在单个 LazyLoad 调用中传递一组 URL

回答by Daniel B?hmer

Try to add a certain CSS rule to the end of your file and wait for the CSS to be applied (check that via JavaScript). After that you can be pretty sure the CSS has been loaded. However I have no experience with that. Just a quick idea might be worth a try.

尝试在文件末尾添加某个 CSS 规则并等待应用 CSS(通过 JavaScript 检查)。之后,您可以非常确定 CSS 已加载。但是我没有这方面的经验。只是一个快速的想法可能值得一试。

回答by Steven Nelson

I wanted to offer some insight into what may have changed.

我想就可能发生的变化提供一些见解。

According to one of the last paragraphs on Mozilla's documentation of <link>, a load event can be attached to a link element in FF versions 9 and up as well as Chrome 19 and up. IE and Safari are not stated. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link

根据 Mozilla 文档的最后一段<link>,加载事件可以附加到 FF 9 及更高版本以及 Chrome 19 及更高版本中的链接元素。IE 和 Safari 没有说明。https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link

回答by Hung Pham

try this: 1- preload css on head

试试这个: 1- 在头上预加载 css

<link rel="preload" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" as="style" onload="this.rel='stylesheet'"> 
<link rel="preload" href="style.css" as="style" onload="this.rel='stylesheet'"> 

2 - preload js file on footer

2 - 在页脚上预加载 js 文件

    <link rel="preload" as="script" href="https://ajax.googleapis.com/ajax/libs/jquery/2.2.1/jquery.min.js">
    <link rel="preload" as="script" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js">
    <link rel="preload" as="script" href="script.js">

3 - before tag </body>add

3 - 在标签</body>添加之前

<script>        
/**  load defer css - js*/  
// defer css
var cssAll = document.querySelectorAll('[as="style"]');
for(i = 0; i < cssAll.length; i++){
    if(cssAll[i].getAttribute("rel") == "preload"){         
        cssAll[i].setAttribute("rel", "stylesheet");
    }
}
//defer js
var jsAll = document.querySelectorAll('[as="script"]');
if(!window.jQuery)
{
    // load jquery lib
    var script = document.createElement('script');
    script.type = "text/javascript";
    script.src = jsAll[0].getAttribute("href");
    document.getElementsByTagName('head')[0].appendChild(script);
   // load other lib after load jquery
    script.onload = function () {
        for(i = 1; i < jsAll.length; i++){
            var jsNext = document.createElement('script');
            jsNext.type = "text/javascript";
            jsNext.src = jsAll[i].getAttribute("href");
            document.getElementsByTagName('head')[0].appendChild(jsNext);
        }
    }   
}
</script>   

I tested on firefox 57, chrome 61, yandex, not tested on opera and ie

我在 firefox 57、chrome 61、yandex 上测试过,没有在 Opera 和 IE 上测试过

回答by jAndy

Using a script loader like Supply, this would look like:

使用像 的脚本加载器Supply,这看起来像:

supply.listen('text/css', function(payload, filename) {
    switch(filename) {
        case: 'foo.css': {
            // do something
            break;
        }
        case: 'baseball.css': {
            break;
        }
        // ...
    }
});

supply.files({
    stylesheet: [
        'foo.css',
        'baseball.css'
    ]
});

Ref.: SupplyJS

参考:SupplyJS

回答by Nicolas

About the "load-checking CSS rules" :

关于“负载检查 CSS 规则”:

If, in your JS script, you append in your head a style tag containing a simple rule like : #loadingCss { display: block; }

如果在您的 JS 脚本中,您在头部附加了一个样式标记,其中包含一个简单的规则,例如:#loadingCss { display: block; }

Than, you just have to add in all your CSS files something like : #loadingCss { display: none; }

然后,您只需添加所有 CSS 文件,例如:#loadingCss { display: none; }

In the head of your doc you append the style tag before the link tag. This way, the CSS rule in the CSS file will be more important (same selector -> same priority, the last one in the doc is the winner).

在您的文档的头部,您将样式标签附加在链接标签之前。这样,CSS 文件中的 CSS 规则就会更加重要(相同的选择器 -> 相同的优先级,文档中的最后一个是赢家)。

Than, in your JS script you just have to check #loadingCss visibility. Once you know your CSS file is loaded, you can remove the style tag.

然后,在您的 JS 脚本中,您只需检查 #loadingCss 可见性。一旦您知道您的 CSS 文件已加载,您就可以删除样式标记。

For the next CSS file you want to load, you can add this style tag again at the end of the head element.

对于您要加载的下一个 CSS 文件,您可以在 head 元素的末尾再次添加此样式标记。

This way, with only one rule, you can manage all your CSS files loading. The only problem with this solution : You can't load more than one CSS file at a time. But I'm sure it's possible to find a way to do so.

这样,只需一条规则,您就可以管理所有 CSS 文件的加载。此解决方案的唯一问题是:一次不能加载多个 CSS 文件。但我相信有可能找到一种方法来做到这一点。

But anyway, I'm not sure this solution (using a CSS rule to check loading) is a very good solution. Maybe there's other ways to do this.

但无论如何,我不确定这个解决方案(使用 CSS 规则检查加载)是一个非常好的解决方案。也许还有其他方法可以做到这一点。

回答by Frane Poljak

This is by far the simplest and best solution I have found so far and it works perfectly:

这是迄今为止我发现的最简单和最好的解决方案,它完美地工作:

var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = css_url;

head.appendChild(link);

var img = document.createElement('img');
document.body.appendChild(img);

img.onerror = img.onload = function() {
    img.onerror = img.onload = null;
    document.body.removeChild(img);
    // do whatever you need to do when css loaded;
};

img.src = css_url;