如何使用 Javascript 加载 CSS 文件?

Posted

技术标签:

【中文标题】如何使用 Javascript 加载 CSS 文件?【英文标题】:How to load up CSS files using Javascript? 【发布时间】:2010-10-09 03:57:02 【问题描述】:

是否可以使用 javascript 将 css 样式表导入 html 页面?如果可以,怎么做?

PS javascript 将托管在我的网站上,但我希望用户能够放入他们网站的 <head> 标记,并且它应该能够将托管在我的服务器上的 css 文件导入当前网络页。 (css 文件和 javascript 文件都将托管在我的服务器上)。

【问题讨论】:

还有关于jQuery的问题***.com/questions/2685614/… 【参考方案1】:

这是“老派”的做法,希望它适用于所有浏览器。理论上,你会使用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 路径是绝对路径,以便从您的服务器加载。

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。

【讨论】:

CSS 文件加载后运行回调怎么样? 要可靠地执行此操作要复杂得多。流行的 Javascript 库现在通常具有某种形式的加载 javascript 和带有回调的样式表。例如,请参阅YUI Get。 也许使用与 $ 不同的字符作为文档快捷方式会更好,因为它很容易干扰 jQuery(就像我的情况一样);) @jonnybojangles 使用 jQuery.noConflict 意味着将所有对 jQuery 的引用重命名为 $。为 CSS 加载器使用不同的变量名会简单得多。 @jchook 我可以通过在附加之前添加link.onload = function() ... 来附加回调【参考方案2】:

如果你使用 jquery:

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

【讨论】:

这只有在页面加载之前注入样式表才有效,对吗?当我在加载页面上的控制台内运行此命令时,该命令带有我在 Dropbox 上托管的 css 文件,它不会工作。知道如何使这项工作:$('head').append('&lt;link rel="stylesheet" type="text/css" href="https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css"&gt;');【参考方案3】:

我猜想这个脚本会做:

<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 的地址必须是绝对地址。

这篇"Say no to CSS hacks with branching techniques" 文章讨论了许多 CSS 导入技术。

但"Using JavaScript to dynamically add Portlet CSS stylesheets" 文章也提到了 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() 添加到没有它的浏览器的方法:***.com/questions/524696/… 不确定究竟是哪种情况,但在某些情况下,不建议使用document.write,因为它会覆盖您网站的整个正文。 @VonC,是否有一个函数可以直接获取&lt;style&gt; 元素,而不是通过("head")[0] 假设它是&lt;head&gt; 的第一个子元素? @Pacerier 我相信您会在groups.google.com/forum/#!topic/prototype-scriptaculous/… 中找到讨论的内容。例如:var style = document.getElementsByTagName("style")[0];【参考方案4】:

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

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

【讨论】:

【参考方案5】:

如果您想知道(或等待)直到样式本身已加载,这可行:

// 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 goes here) 阅读承诺【参考方案6】:

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

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

Official docs on promises

Useful guide to promises

A great intro video on promises

【讨论】:

【参考方案7】:

使用此代码:

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

【讨论】:

【参考方案8】:

我知道这是一个很老的话题,但我的 5 美分来了。

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

我有一个案例,我希望一个 css 文件只激活一段时间。就像css切换一样。激活 css,然后在另一个事件之后将其停用。

您可以在新 css 中的所有元素前面添加一个类/一个 id,而不是动态加载 css 然后将其删除,然后只需切换 css 基节点的类/id(如 body 标签) .

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

【讨论】:

【参考方案9】:

你听说过 Promise 吗?它们适用于所有现代浏览器,并且使用起来相对简单。看看这个将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://***.com/a/63936671/13720928

【讨论】:

【参考方案10】:

有一个通用的 jquery 插件,可以按需加载 css 和 JS 文件同步和异步。 它还跟踪已经加载的内容:) 见:http://code.google.com/p/rloader/

【讨论】:

【参考方案11】:

这里有 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);

【讨论】:

【参考方案12】:

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

【讨论】:

我认为 .onreadystatechangethis.readyState 不存在。当我尝试使用script 对象时,唯一的事件工作是来自这里的许多事件的.onload()(developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers)似乎没有其他工作。【参考方案13】:

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

document.head.innerHTML += '&lt;link rel="stylesheet" href="css/style.css"&gt;';

大多数浏览器都支持它。请参阅browser compatibility。

【讨论】:

【参考方案14】:

您可以使用此YUI library 或使用此article to implement

【讨论】:

【参考方案15】:

YUI library 可能是您正在寻找的。它还支持跨域加载。

如果你使用 jquery,this plugin 会做同样的事情。

【讨论】:

【参考方案16】:

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

【讨论】:

【参考方案17】:
var elem = document.createElement('link');
elem.rel = ' stylesheet'
elem.href= 'style.css';//Link of the css file
document.head.appendChild(elem);

【讨论】:

欢迎来到 ***!请提供与您发布的代码相关的说明 请检查您的解决方案之前是否未在其中一个答案中发布。看来,accepted answer 提出了相同的解决方案。【参考方案18】:
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 不会处理它,所以这里看起来是多余的。【参考方案19】:

使用:

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

【讨论】:

以上是关于如何使用 Javascript 加载 CSS 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在局部视图中加载 JavaScript CSS 文件

如何使用 WKWebview 从 iPad 的 Document 目录加载 javascript 和 css 资源?

如何从外部从 GitHub 加载 JavaScript 文件? [复制]

如何动态加载外部 CSS 文件?

JavaScript 文件中的代码如何获取文件的 URL?

Thymeleaf 加载 CSS 但不加载 Javascript