如何使用Javascript加载CSS文件?


316

是否可以使用Javascript将CSS样式表导入html页面?如果是这样,怎么办?

附言:JavaScript将会托管在我的网站上,但我希望用户能够放入<head>其网站的标签,并且它应该能够将托管在我的服务器上的CSS文件导入当前网页。(css文件和javascript文件都将托管在我的服务器上)。


还有关于jQuery的问题stackoverflow.com/questions/2685614/...
jcubic

Answers:


416

这是这样做的“老派”方法,希望可以在所有浏览器上使用。从理论上讲,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.com/css/stylesheet.css';
    link.media = 'all';
    head.appendChild(link);
}

本示例检查CSS是否已添加,因此仅添加一次。

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

香草

这是一个使用普通JavaScript head根据URL的文件名部分将CSS链接注入元素的示例:

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


6
CSS文件加载后如何运行回调?
jchook 2012年

1
要可靠地做到这一点,要复杂得多。现在,流行的Javascript库通常具有某种形式的通过回调加载JavaScript和样式表的方式。例如,请参见YUI Get

9
也许最好使用一个不同的字符而不是$作为文档快捷方式,因为它很容易干扰jQuery(就像我的情况一样;);)
Zathrus Writer

2
@jonnybojangles使用jQuery.noConflict意味着将所有对jQuery的引用重命名为$。仅对CSS加载器使用不同的变量名会更简单。
tommypyatt 2014年

2
@jchook我能够在添加link.onload = function(){ ... }之前添加一个附加的回调
Lounge9,2014年

74

如果使用jQuery:

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

1
仅在样式加载是在页面加载之前注入的情况下才有效吗?当我在控制台上的已加载页面上运行此命令时,如果我在Dropbox上托管了一个CSS文件,它将无法正常工作。任何想法我怎么做这项工作:$('head').append('<link rel="stylesheet" type="text/css" href="https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css">');
托马斯

50

我猜像这样的脚本可以做到:

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

该JS文件包含以下语句:

if (!document.getElementById) document.write('<link rel="stylesheet" type="text/css" href="https://stackoverflow.com/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);
}
//]]>

这是我想添加document.createStyleSheet()到没有它的浏览器中的内容:stackoverflow.com/questions/524696/…–
Christoph

1
不确定到底是哪种情况,但在某些情况下,document.write我们不建议这样做,因为它会覆盖网站的整个主体。
爱德华·卢卡

@VonC,是否有一个函数可以直接获取<style>元素,而不是假设它是<head>via 的第一个子元素("head")[0]
Pacerier,2014年

@Pacerier,我相信您会在groups.google.com/forum /#!topic / prototype-scriptaculous / ...中进行讨论。例如:var style = document.getElementsByTagName("style")[0];
VonC 2014年

20

Element.insertAdjacentHTML具有非常好的浏览器支持,并且可以在一行中添加样式表。

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

12

如果您想知道(或等待)样式本身已加载,则可以这样做:

// 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 = function() { resolve(); console.log('style has loaded'); };
    link.href = url;

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

我如何使用它
拉吉·沙尔玛

您会做fetchStyle(url).then(function(){stuff go here})阅读诺言
Ben Taliadoros,

8

我知道这是一个很旧的线程,但是我的5美分在这里。

有另一种方法可以执行此操作,具体取决于您的需求。

我有一种情况,我希望CSS文件仅在一段时间内处于活动状态。就像CSS切换一样。激活css,然后在另一个事件后将其激活。

除了动态加载css然后删除它之外,您可以在新css中所有元素的前面添加一个Class / id,然后只需切换该CSS基本节点的class / id(例如body标签)即可。

使用此解决方案,您最初会加载更多的css文件,但是您可以使用更动态的方式切换css布局。


7

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

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

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

承诺的官方文档

有用的诺言指南

关于诺言的精彩介绍视频


6

使用此代码:

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


4

这是使用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);



2

下面是用于加载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'])) ();

1

我想分享另一种方法,不仅可以加载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文档


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

我正在使用百里香,这很好用。谢谢


th:href在客户端添加属性有什么意义?Thymeleaf不会处理它,因此在这里似乎多余。
Slava Semushin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.