如何使用Javascript来检查和加载CSS,如果没有加载?
我需要检查(在Javascript中)是否加载了CSS文件,如果没有加载它。 jQuery很好。
只需检查一下<link>
元素是否存在,并将href
属性设置为CSS文件的URL:
if (!$("link[href='/path/to.css']").length) $('<link href="/path/to.css" rel="stylesheet">').appendTo("head");
原汁原味的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();
我只是不得不写这样的东西,我想分享它。 这个是为多个案件准备的。
- 如果没有请求的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 } }
更新 :由于我的答案有几个upvotes,这导致我修改代码,我决定更新它。
// 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 // Eg 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
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. } }
这样的事情会做(使用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 + '" />') ); } }
与JFK对接受的答案所做的评论一样:
我把这个问题理解为“如何检查一个css文件是否被加载”而不是“如何检查该元素是否存在”。
该元素可能存在(并且path也可能是正确的),但这并不意味着该css文件已成功加载。
如果通过getElementById
访问链接元素,则无法检查/读取CSS文件中定义的样式。
为了检查样式是否已经成功加载,我们必须使用getComputedStyle
(或IE的currentStyle
)。
HTML
//somewhere in your html document <div id="css_anchor"></div>
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); } });
部分答案来自: 在主样式表中设置myDiv.style.display时返回空白
在这里演示: http : //jsfiddle.net/R9F7R/
我的2美分。 这检查是否有任何规则在CSS上设置,这意味着它是否成功加载
if(jQuery("link[href='/style.css']").prop('sheet').cssRules.length == 0){ //Load the css you want }
除了上面的所有好的答案,你可以简单地把一个虚拟元素放在你的标记和你的css文件中,给它任何样式,而不是默认的。 然后在代码中检查属性是否应用于哑元素,如果没有,加载CSS。 只是一个想法,而不是一个干净的方式做你想做的事情。
一种方法是:使用document.getElementsByTagName("link")
遍历每一个,并检查它的href
是否等于你检查的CSS文件。
另一种方法:如果你知道一些CSS规则只在该文件中被设置,检查这个规则是否真的适用,比如检查背景是否真的是红色的。
您可以检查文件名是否在您的标记内,如:
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); }
或者你可以检查一个应该可用的特定的className
,如果样式表被加载的话。 这可能会更接近特征检测。
文档对象包含一个包含所有加载样式表的样式表集合。
参考http://www.javascriptkit.com/domref/stylesheet.shtml
你可以循环这个集合来validation你想validation的样式表是否在它里面,然后由浏览器加载。
document.styleSheets[0] //access the first external style sheet on the page
有一些浏览器不兼容,但你应该注意。
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); }
为了获得良好的一致性和可重复的体验,我编写了这两个模仿$.getScript(url, callback)
jQuery方法的jQuery插件(但是它们不会像$.getScript()
那样强制从服务器重新加载。 :一个可以在任何时候调用CSS文件的加载器,一个只加载一次CSS文件,我发现前者在进行修改时很方便,而后者则用于快速部署。
/** * An AJAX method to asynchronously load a CACHED CSS resource * Note: This removes the jQuery default behaviour of forcing a refresh by means * of appending a datestamp to the request URL. Actual caching WILL be subject to * server/browser policies */ $.getCachedCss = function getCachedCss(url, callback) { $('<link>',{rel:'stylesheet', type:'text/css', 'href':url, media:'screen'}).appendTo('head'); if (typeof callback == 'function') callback(); } /** * An AJAX method to asynchronously load a CACHED CSS resource Only ONCE. * Note: This removes the jQuery default behaviour of forcing a refresh by means * of appending a datestamp to the request URL. Actual caching WILL be subject to * server/browser policies */ $.getCachedCssOnce = function getCachedCssOnce(url, callback) { if (!$("link[href='" + url + "']").length) { $.getCachedCss(url, callback); if (typeof callback == 'function') callback(); } }
用法示例:
$(function() { $.getCachedCssOnce("pathToMyCss/main.css"); )}
callback用法示例:
$(function() { $.getCachedCssOnce("pathToMyCss/main.css", function() { // Do something once the CSS is loaded });