如果未加载,如何使用 Javascript 检查和加载 CSS?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4724606/
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-08-23 13:46:41  来源:igfitidea点击:

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

javascriptjquerycss

提问by SaltLake

I need to check (in Javascript) if a CSS file is loaded and if not then to load it. jQuery is fine.

我需要检查(在 Javascript 中)是否加载了 CSS 文件,如果没有则加载它。jQuery 很好。

回答by Andy E

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

只需检查是否<link>存在href属性设置为 CSS 文件 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:

简单的 ol' JS 方法也很简单,使用document.styleSheets 集合

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();

回答by akinuri

I just had to write something like that and I wanted to share it. This one is prepared for multiple cases.

我只是不得不写一些类似的东西,我想分享它。这是为多种情况准备的。

  • If there is no request for the css file (css file isn't linked ...)
  • If there is a request for the css file, but if it failed (css file is no longer available ...)
  • 如果没有对 css 文件的请求(css 文件未链接...)
  • 如果有对css文件的请求,但是如果失败(css文件不再可用...)


var styles = document.styleSheets;
for (var i = 0; i < styles.length; i++) {
    // checking if there is a request for template.css
    if (styles[i].href.match("template")) {
        console.log("(Iteration: " + i + ") Request for template.css is found.");
        // checking if the request is not successful
        // when it is successful .cssRules property is set to null
        if (styles[i].cssRules != null && styles[i].cssRules.length == 0) {
            console.log("(Iteration: " + i + ") Request for template.css failed.");
            // fallback, make your modification
            // since the request failed, we don't need to iterate through other stylesheets
            break;
        } else {
            console.log("(Iteration: " + i + ") Request for template.css is successful.");
            // template.css is loaded successfully, we don't need to iterate through other stylesheets
            break;
        }
    }
    // if there isn't a request, we fallback
    // but we need to fallback when the iteration is done
    // because we don't want to apply the fallback each iteration
    // it's not like our css file is the first css to be loaded
    else if (i == styles.length-1) {
        console.log("(Iteration: " + i + ") There is no request for template.css.");
        // fallback, make your modification
    }
}

TL;DR version

TL;DR 版本

var styles = document.styleSheets;
for (var i = 0; i < styles.length; i++) {
    if (styles[i].href.match("css-file-name-here")) {
        if (styles[i].cssRules != null && styles[i].cssRules.length == 0) {
            // request for css file failed, make modification
            break;
        }
    } else if (i == styles.length-1) {
        // there is no request for the css file, make modification
    }
}


Update: Since my answer got a few upvotes and this led me to revise the code, I decided to update it.

更新:由于我的回答获得了一些赞成票,这促使我修改了代码,因此我决定对其进行更新。

// document.styleSheets holds the style sheets from LINK and STYLE elements
for (var i = 0; i < document.styleSheets.length; i++) {

    // Checking if there is a request for the css file
    // We iterate the style sheets with href attribute that are created from LINK elements
    // STYLE elements don't have href attribute, so we ignore them
    // We also check if the href contains the css file name
    if (document.styleSheets[i].href && document.styleSheets[i].href.match("/template.css")) {

        console.log("There is a request for the css file.");

        // Checking if the request is unsuccessful
        // There is a request for the css file, but is it loaded?
        // If it is, the length of styleSheets.cssRules should be greater than 0
        // styleSheets.cssRules contains all of the rules in the css file
        // E.g. b { color: red; } that's a rule
        if (document.styleSheets[i].cssRules.length == 0) {

            // There is no rule in styleSheets.cssRules, this suggests two things
            // Either the browser couldn't load the css file, that the request failed
            // or the css file is empty. Browser might have loaded the css file,
            // but if it's empty, .cssRules will be empty. I couldn't find a way to
            // detect if the request for the css file failed or if the css file is empty

            console.log("Request for the css file failed.");

            // There is a request for the css file, but it failed. Fallback
            // We don't need to check other sheets, so we break;
            break;
        } else {
            // If styleSheets.cssRules.length is not 0 (>0), this means 
            // rules from css file is loaded and the request is successful
            console.log("Request for the css file is successful.");
            break;
        }
    }
    // If there isn't a request for the css file, we fallback
    // But only when the iteration is done
    // Because we don't want to apply the fallback at each iteration
    else if (i == document.styleSheets.length - 1) {
        // Fallback
        console.log("There is no request for the css file.");
    }
}

TL;DR

TL; 博士

for (var i = 0; i < document.styleSheets.length; i++) {
    if (document.styleSheets[i].href && document.styleSheets[i].href.match("/template.css")) {
        if (document.styleSheets[i].cssRules.length == 0) {
            // Fallback. There is a request for the css file, but it failed.
            break;
        }
    } else if (i == document.styleSheets.length - 1) {
        // Fallback. There is no request for the css file.
    }
}

回答by RafaSashi

Peer to the comment made by JFK about the accepted answer:

与肯尼迪对接受的答案发表的评论相同:

I understood the question as "how to check whether a css file is loaded or not" rather than "how to check if the element exists".

The element may exist (and the path may be correct too) but it doesn't mean that the css file was successful loaded.

我将问题理解为“如何检查 css 文件是否已加载”而不是“如何检查元素是否存在”。

该元素可能存在(路径也可能正确),但这并不意味着 css 文件已成功加载。

If you access a link Element via getElementByIdyou'll not be able to check/read the style defined inside the CSS file.

如果您通过访问链接元素, getElementById您将无法检查/读取 CSS 文件中定义的样式。

In order to check if a style has been successfully loaded we have to use getComputedStyle(or currentStylefor IE).

为了检查样式是否已成功加载,我们必须使用getComputedStyle(或currentStyle用于 IE)。

HTML

HTML

//somewhere in your html document

<div id="css_anchor"></div>

CSS

CSS

//somewhere in your main stylesheet

#css_anchor{display:none;}

JAVASCRIPT

爪哇脚本

//js function to check the computed value of a style element

function get_computed_style(id, name){

        var element = document.getElementById(id);

        return element.currentStyle ? element.currentStyle[name] : window.getComputedStyle ? window.getComputedStyle(element, null).getPropertyValue(name) : null;

}

 //on document ready check if #css_anchor has been loaded

    $(document).ready( function() {

            if(get_computed_style('css_anchor', 'display')!='none'){

            //if #css_anchor style doesn't exist append an alternate stylesheet

                var alternateCssUrl = 'http://example.com/my_alternate_stylesheet.css';

                var stylesheet = document.createElement('link');

                stylesheet.href = alternateCssUrl;
                stylesheet.rel = 'stylesheet';
                stylesheet.type = 'text/css';
                document.getElementsByTagName('head')[0].appendChild(stylesheet);

            }
    });

Part of the answer comes from: myDiv.style.display returns blank when set in master stylesheet

部分答案来自:myDiv.style.display 在主样式表中设置时返回空白

Demo here: http://jsfiddle.net/R9F7R/

演示在这里:http: //jsfiddle.net/R9F7R/

回答by Sean Patrick Floyd

Something like this will do (using jQuery):

这样的事情会做(使用jQuery):

function checkStyleSheet(url){
   var found = false;
   for(var i = 0; i < document.styleSheets.length; i++){
      if(document.styleSheets[i].href==url){
          found=true;
          break;
      }
   }
   if(!found){
       $('head').append(
           $('<link rel="stylesheet" type="text/css" href="' + url + '" />')
       );
   }
}

回答by Samnan

Apart from all the nice answers above, you can simply put a dummy element inside your markup and in your css file, give it any style other than default. Then in the code check if the attribute is applied to the dummy element, and if not, load the css. Just a thought though, not a neat way to do that thing you want done.

除了上面所有不错的答案之外,您还可以简单地在标记和 css 文件中放置一个虚拟元素,为其指定除默认值以外的任何样式。然后在代码中检查该属性是否应用于虚拟元素,如果没有,则加载css。只是一个想法,而不是做你想做的事情的巧妙方法。

回答by jpbourbon

My 2 cents. This checks whether there are any rules set on the css or not, meaning that it was or not successfully loaded

我的 2 美分。这将检查 css 是否设置了任何规则,这意味着它是否已成功加载

if(jQuery("link[href='/style.css']").prop('sheet').cssRules.length == 0){
    //Load the css you want
}

回答by Shadow Wizard is Ear For You

One way: use document.getElementsByTagName("link")iterate over each and check if its hrefis equal to the CSS file you check.

一种方法:document.getElementsByTagName("link")对每个使用迭代并检查它href是否等于您检查的 CSS 文件。

Another way: if you know some CSS rule being set only in that file, check if this rule really apply e.g. check if background of something is really red.

另一种方法:如果您知道某些 CSS 规则仅在该文件中设置,请检查此规则是否真的适用,例如检查某些东西的背景是否真的是红色的。

回答by joksnet

var links = document.getElementsByTagName('link');
var file  = 'my/file.css';
var found = false;

for ( var i in links )
{
    if ( links[i].type == 'text/css' && file == links[i].href ) {
        found = true; break;
    }
}

if ( !( found ) ) {
    var styles = document.getElementsByTagName('style');
    var regexp = new RegExp('/\@import url\("?' + file + '"?\);/');

    for ( var i in styles )
    {
        if ( styles[i].src == file ) {
            found = true; break;
        } else if ( styles[i].innerHTML.match(regexp) ) {
            found = true; break;
        }
    }
}

if ( !( found ) ) {
    var elm = document.createElement('link');
        elm.href = file;
    document.documentElement.appendChild(elm);
}

回答by jAndy

You can either check if the filename is within your markup, like:

您可以检查文件名是否在您的标记中,例如:

var lnks    = document.getElementsByTagName('link'),
    loadcss = true;

for(var link in lnks) {
    href = link.getAttribute('href');

    if( href.indexOf('foooobar.css') > -1) ){
            loadcss = false;
            return false;
    }
});

if( loadcss ) {
        var lnk     = document.createElement('link'),
            head    = document.getElementsByTagName('head')[0] || document.documentElement;        

        lnk.rel     = 'stylesheet';
        lnk.type    = 'text/css';
        lnk.href    = '//' + location.host + 'foooobar.css';            

        head.insertBefore(lnk, head.firstChild);
}

or you could check for a specific classNamewhich should be available, if the stylesheet was loaded. This probably comes a little closer to a feature detection.

或者className,如果加载了样式表,您可以检查应该可用的特定内容。这可能更接近于特征检测。

回答by Peter

The document object contains a stylesheet collection with all the loaded stylesheets.

文档对象包含一个带有所有加载的样式表的样式表集合。

For a reference see http://www.javascriptkit.com/domref/stylesheet.shtml

有关参考,请参阅http://www.javascriptkit.com/domref/stylesheet.shtml

You can loop this collection to verify that the stylesheet you want to verify is in it and thus loaded by the browser.

您可以循环此集合以验证您要验证的样式表是否在其中并由浏览器加载。

document.styleSheets[0] //access the first external style sheet on the page

There are some browser incompatibilities you should look out for though.

不过,您应该注意一些浏览器不兼容问题。