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

IT技术 javascript jquery css
2021-03-13 15:57:43

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

6个回答

只需检查是否<link>存在href属性设置为 CSS 文件 URL元素

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

简单的 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();
@AndyE 仅供参考 - 与 jmc 一样,我偶尔会遇到一个随机的单个脚本/css 文件无法加载,而页面上的所有其他文件都加载了。是的,它们都来自同一个域,批量同时加载,不,这不是文件内容的兼容性问题。如果访问者重新加载页面,则相关文件会成功加载(换句话说,重新加载成功)。我的观点是它可以并且确实发生,并且需要检测特定资源是否已加载是合法的。
2021-04-26 15:57:43
我将问题理解为“如何检查 css 文件是否已加载”而不是“如何检查<link>元素是否存在”。<link>元素可能存在(路径也可能正确),但这并不意味着 css 文件已成功加载。因此,重新提出问题:如果未加载 css 文件(例如与 cdn 服务器的通信问题),如何改为加载(本地)css(后备)文件?
2021-05-07 15:57:43
问题说“加载”,而不是“链接到”。此答案检查样式表是否已链接,但不检查是否已实际加载。有关问题的正确答案,请参阅@RafaSashi 的答案。
2021-05-09 15:57:43
跨浏览器如何document.styleSheets
2021-05-10 15:57:43
这不是这个问题的答案。
2021-05-11 15:57:43

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

  • 如果没有对 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 版本

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
    }
}

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

// 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; 博士

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.
    }
}
这不起作用。如果样式表在文档中链接,无论它是否已加载,您都会得到一个匹配项。如果它尚未加载,则无法根据 来检查 cssRules 值null,或检查其长度。你会得到Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules
2021-04-22 15:57:43
在这里phpied.com/when-is-a-stylesheet-really-loaded有一个适用于 Firefox 的解决方法
2021-04-28 15:57:43
在 Firefox 中访问 c​​ssRules 会抛出安全错误
2021-05-02 15:57:43
在 Firefox 中,如果 CSS 还没有完成解析,则尝试调用cssRules将失败,并显示错误 InvalidAccessError: A parameter or an operation is not supported by the Abyss
2021-05-13 15:57:43

这样的事情会做(使用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 + '" />')
       );
   }
}
这行不通。如果样式表在文档中被链接,它将以document.styleSheets它是否已加载来表示通过链接到带有无效 URL 的样式表来测试它。它仍然会在那里。
2021-05-09 15:57:43

与 JFK 对已接受答案的评论一致:

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

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

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

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

HTML

//somewhere in your html document

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

CSS

//somewhere in your main stylesheet

#css_anchor{display:none;}

Java脚本

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

            }
    });

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

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

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