JavaScriptを使用してCSSファイルをロードする方法


316

JavaScriptを使用してCSSスタイルシートをHTMLページにインポートすることは可能ですか?もしそうなら、それはどのように行うことができますか?

PS JavaScriptは私のサイトでホストされますが、ユーザー<head>が自分のWebサイトのタグを挿入できるようにして、サーバーでホストされているCSSファイルを現在のWebページにインポートできるようにする必要があります。(cssファイルとjavascriptファイルの両方が私のサーバーでホストされます)。


回答:


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パスが絶対パスであることを確認して、サーバーからロードされるようにします。

バニラJS

以下は、プレーン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)が表示されます。


6
CSSファイルがロードされたらコールバックを実行するのはどうですか?
jchook '19年

1
これは確実に行うにはかなり複雑です。現在、人気のあるJavaScriptライブラリには、通常、コールバックを使用してJavaScriptとスタイルシートをロードする何らかの形式があります。例として、YUI Getを参照してください。

9
おそらくドキュメントのショートカットには$とは別の文字を使用する方が良いでしょう。これはjQueryを簡単に妨害する可能性があるためです(私の場合と同様);)
Zathrus Writer

2
@jonnybojangles jQuery.noConflictを使用すると、jQueryへのすべての参照の名前が$に変更されます。CSSローダーに別の変数名を使用する方がはるかに簡単です。
tommypyatt 14年

2
@jchook追加するlink.onload = function(){ ... }前に追加することでコールバックを添付できました
Lounge9

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を使用してポートレット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
Christoph

1
どちらの場合が正確かはわかりませんが、場合によってdocument.writeは、Webサイト全体が上書きされるため、お勧めできません。
Eduard Luca

@ VonC、viaの<style>最初の子であると仮定する代わりに、要素を直接取得する関数はありますか?<head>("head")[0]
Pacerier 2014

@Paceriergroups.google.com/forum/#!topic/prototype-scriptaculous/…で説明されていることがわかると思います。それは、例えば次のようになりますvar style = document.getElementsByTagName("style")[0];
VonC

20

Element.insertAdjacentHTMLは非常に優れたブラウザサポートを備えており、1行でスタイルシートを追加できます。

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

使用方法
Raj Sharma

あなたはfetchStyle(url).then(function(){stuff
go

8

私はこれがかなり古いスレッドであることを知っていますが、ここに私の5セントが来ます。

ニーズに応じて、これを行う別の方法があります。

CSSファイルをしばらくだけアクティブにしたい場合があります。CSSスイッチングと同様。CSSをアクティブにしてから、別のイベントの後に非アクティブ化します。

CSSを動的にロードして削除する代わりに、新しいCSSのすべての要素の前にクラス/ IDを追加し、CSSのベースノードのそのクラス/ IDを切り替えることができます(ボディタグなど)。

このソリューションでは、最初に読み込まれる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

CSSとJSファイルをオンデマンドで同期および非同期でロードする一般的なjqueryプラグインがあります。また、すでにロードされているものも追跡します :)参照:http : //code.google.com/p/rloader/


4

jQueryの要素作成メソッド(私の設定)とcallbackを使用する方法を次に示します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イベントを処理するもう1つの方法を共有したいと思います。です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 docsによると


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

私はthymeleafを使用していますが、これは問題なく動作します。ありがとう


th:hrefクライアント側で属性を追加するポイントは何ですか?Thymeleafで処理されないため、ここでは冗長なようです。
Slava Semushin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.