如何使用Javascript加载CSS文件?

是否有可能导入css样式表到一个html页面使用Javascript?如果是,该怎么做呢?

p.s. javascript将托管在我的网站上,但我希望用户能够把他们的网站的<head>标签,它应该能够导入一个css文件托管在我的服务器到当前的网页。(CSS文件和javascript文件都将托管在我的服务器上)。

630197 次浏览

我想类似这样的脚本可以做到:

<script type="text/javascript" src="/js/styles.js"></script>

这个JS文件包含以下语句:

if (!document.getElementById) document.write('<link rel="stylesheet" type="text/css" href="/css/versions4.css">');

javascript和css的地址需要是绝对的,如果他们是指你的网站。

许多CSS导入技术将在这篇“用分支技术对CSS黑客说不”文章中讨论。

但是使用JavaScript动态添加Portlet CSS样式表文章还提到了CreateStyleSheet的可能性(IE的专有方法):

<script type="text/javascript">
//<![CDATA[
if(document.createStyleSheet) {
document.createStyleSheet('http://server/stylesheet.css');
}
else {
var styles = "@import url(' http://server/stylesheet.css ');";
var newSS=document.createElement('link');
newSS.rel='stylesheet';
newSS.href='data:text/css,'+escape(styles);
document.getElementsByTagName("head")[0].appendChild(newSS);
}
//]]>

你可以使用这个YUI库或使用这个实施条款

YUI库可能就是你要找的。它还支持跨域加载。

如果你使用jquery, 这个插件做同样的事情。

这是“老派”;这是一种方法,希望在所有浏览器上都适用。理论上,你会使用setAttribute,不幸的是,IE6并不始终支持它。

var cssId = 'myCss';  // you could encode the css path itself to generate id..
if (!document.getElementById(cssId))
{
var head  = document.getElementsByTagName('head')[0];
var link  = document.createElement('link');
link.id   = cssId;
link.rel  = 'stylesheet';
link.type = 'text/css';
link.href = 'http://website.example/css/stylesheet.css';
link.media = 'all';
head.appendChild(link);
}

这个例子检查CSS是否已经添加,所以只添加一次。

将该代码放入JavaScript文件中,让最终用户简单地包含JavaScript,并确保CSS路径是绝对的,以便从服务器加载它。

VanillaJS

下面是一个例子,使用纯JavaScript根据URL的文件名部分将CSS链接注入到head元素中:

<script type="text/javascript">
var file = location.pathname.split( "/" ).pop();


var link = document.createElement( "link" );
link.href = file.substr( 0, file.lastIndexOf( "." ) ) + ".css";
link.type = "text/css";
link.rel = "stylesheet";
link.media = "screen,print";


document.getElementsByTagName( "head" )[0].appendChild( link );
</script>

在结束head标记之前插入代码,CSS将在页面呈现之前加载。使用外部JavaScript (.js)文件将导致出现非样式内容(FOUC)的Flash。

这是一个通用的jquery插件,可以根据需要加载css和JS文件的同步和异步。 它还可以跟踪已经加载的内容:) 看到:http://code.google.com/p/rloader/ < / p >

我知道这是一个相当老的帖子,但这里是我的5美分。

根据您的需要,还有另一种方法可以做到这一点。

我有一个情况下,我想要一个css文件是活跃的,只有一段时间。比如css切换。激活css,然后在另一个事件后取消激活它。

而不是动态加载css然后删除它,你可以在新css的所有元素前添加一个Class/ id,然后只需切换css的基本节点的Class/ id(如body标签)。

你会用这个解决方案有更多的css文件最初加载,但你有一个更动态的方式切换css布局。

var fileref = document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("th:href", "@{/filepath}")
fileref.setAttribute("href", "/filepath")

我用的是百里香叶,效果很好。谢谢

下面是一种使用jQuery的元素创建方法(我的偏好)和回调onLoad的方法:

var css = $("<link>", {
"rel" : "stylesheet",
"type" :  "text/css",
"href" : "style.css"
})[0];


css.onload = function(){
console.log("CSS IN IFRAME LOADED");
};


document
.getElementsByTagName("head")[0]
.appendChild(css);

如果你使用jquery:

$('head').append('<link rel="stylesheet" type="text/css" href="style.css">');

下面是用于加载JS和/或CSS的完整代码

function loadScript(directory, files){
var head = document.getElementsByTagName("head")[0]
var done = false
var extension = '.js'
for (var file of files){
var path = directory + file + extension
var script = document.createElement("script")
script.src = path
script.type = "text/javascript"
script.onload = script.onreadystatechange = function() {
if ( !done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") ) {
done = true
script.onload = script.onreadystatechange = null   // cleans up a little memory:
head.removeChild(script)  // to avoid douple loading
}
};
head.appendChild(script)
done = false
}
}


function loadStyle(directory, files){
var head = document.getElementsByTagName("head")[0]
var extension = '.css'
for (var file of files){
var path = directory + file + extension
var link = document.createElement("link")
link.href = path
link.type = "text/css"
link.rel = "stylesheet"
head.appendChild(link)
}
}


(() => loadScript('libraries/', ['listen','functions', 'speak', 'commands', 'wsBrowser', 'main'])) ();
(() => loadScript('scripts/', ['index'])) ();


(() => loadStyle('styles/', ['index'])) ();

如果你想知道(或等待)直到样式本身加载,这是有效的:

// this will work in IE 10, 11 and Safari/Chrome/Firefox/Edge
// add ES6 poly-fill for the Promise, if needed (or rewrite to use a callback)


let fetchStyle = function(url) {
return new Promise((resolve, reject) => {
let link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.onload = () => resolve();
link.onerror = () => reject();
link.href = url;


let headScript = document.querySelector('script');
headScript.parentNode.insertBefore(link, headScript);
});
};

用法:

fetchStyle(url)
.then(
() => console.log("style loaded succesfully"),
() => console.error("style could not be loaded"),
);

使用以下代码:

var element = document.createElement("link");
element.setAttribute("rel", "stylesheet");
element.setAttribute("type", "text/css");
element.setAttribute("href", "external.css");
document.getElementsByTagName("head")[0].appendChild(element);

Element.insertAdjacentHTML有很好的浏览器支持,可以在一行中添加一个样式表。

document.getElementsByTagName("head")[0].insertAdjacentHTML(
"beforeend",
"<link rel=\"stylesheet\" href=\"path/to/style.css\" />");

在现代浏览器中,你可以像这样使用promise。创建一个带有promise的loader函数:

function LoadCSS( cssURL ) {


// 'cssURL' is the stylesheet's URL, i.e. /css/styles.css


return new Promise( function( resolve, reject ) {


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


link.rel  = 'stylesheet';


link.href = cssURL;


document.head.appendChild( link );


link.onload = function() {


resolve();


console.log( 'CSS has loaded!' );
};
} );
}

显然,你想在CSS加载后完成一些事情。你可以像这样调用CSS加载后需要运行的函数:

LoadCSS( 'css/styles.css' ).then( function() {


console.log( 'Another function is triggered after CSS had been loaded.' );


return DoAfterCSSHasLoaded();
} );

如果你想深入了解它是如何工作的,有用的链接:

承诺的官方文件

承诺的有用指南

一个关于承诺的很棒的介绍视频

我想分享另一种方法,不仅加载css,而且所有的资产(js, css,图像),并处理onload事件的一堆文件。async-assets-loader。请看下面的例子:

<script src="https://unpkg.com/async-assets-loader"></script>
<script>
var jsfile = "https://code.jquery.com/jquery-3.4.1.min.js";
var cssfile = "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css";
var imgfile = "https://logos.keycdn.com/keycdn-logo-black.png";
var assetsLoader = new asyncAssetsLoader();
assetsLoader.load([
{uri: jsfile, type: "script"},
{uri: cssfile, type: "style"},
{uri: imgfile, type: "img"}
], function () {
console.log("Assets are loaded");
console.log("Img width: " + assetsLoader.getLoadedTags()[imgfile].width);
});
</script>

根据async-assets-loader文档

var elem = document.createElement('link');
elem.rel = ' stylesheet'
elem.href= 'style.css';//Link of the css file
document.head.appendChild(elem);

使用:

document.getElementById("of head/body tag")
.innerHTML += '<link rel="stylesheet" type="text/css" href="style.css">';

下面是一个一行的例子,它使用纯JavaScript根据URL的文件名部分将CSS链接注入到head元素中:

document.head.innerHTML += '<link rel="stylesheet" href="css/style.css">';

大多数浏览器都支持它。参见浏览器兼容性

你听说过《承诺》吗?它们适用于所有现代浏览器,而且使用起来相对简单。看看这个简单的方法,将css注入到html头部:

function loadStyle(src) {
return new Promise(function (resolve, reject) {
let link = document.createElement('link');
link.href = src;
link.rel = 'stylesheet';


link.onload = () => resolve(link);
link.onerror = () => reject(new Error(`Style load error for ${src}`));


document.head.append(link);
});
}

你可以这样实现它:

window.onload = function () {
loadStyle("https://fonts.googleapis.com/css2?family=Raleway&display=swap")
.then(() => loadStyle("css/style.css"))
.then(() => loadStyle("css/icomoon.css"))
.then(() => {
alert('All styles are loaded!');
}).catch(err => alert(err));
}

这真的很酷,对吧?这是一种使用Promises来决定样式优先级的方法。

要查看多风格加载实现,请参见:https://stackoverflow.com/a/63936671/13720928

这个函数使用记忆。并且可以多次调用,而不会出现两次加载和运行相同样式表的冲突。而且,它不会在样式表实际加载之前解析。

const loadStyle = function () {
let cache = {};
return function (src) {
return cache[src] || (cache[src] = new Promise((resolve, reject) => {
let s = document.createElement('link');
s.rel = 'stylesheet';
s.href = src;
s.onload = resolve;
s.onerror = reject;
document.head.append(s);
}));
}
}();

请注意函数表达式后面的括号()。

样式表的并行加载:

Promise.all([
loadStyle('/style1.css'),
loadStyle('/style2.css'),
// ...
]).then(() => {
// do something
})

你可以对动态加载脚本使用相同的方法。

来自未来的回答。 在2022年,我们有导入断言api用于导入css文件

import mycss from "./style/mycss.css" assert { type: "css" };
document.adoptedStyleSheets = [sheet];
shadowRoot.adoptedStyleSheets = [sheet];
< p >浏览器支持: 直到2022年9月,只支持基于铬的浏览器

阅读更多: V8导入断言post < / p > < p > tc39 github T39导入断言建议 < / p >