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

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


当前回答

下面是一种“老派”的方法,希望它适用于所有浏览器。理论上,你可以使用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注入一个CSS链接到head元素基于URL的文件名部分:

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

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

其他回答

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

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

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

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

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

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

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

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

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

在现代浏览器中,您可以使用这样的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();
} );

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

官方承诺文件

有关承诺的有用指南

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