Wie lade ich CSS-Dateien mit Javascript?

316

Ist es möglich, CSS-Stylesheets mit Javascript in eine HTML-Seite zu importieren? Wenn ja, wie geht das?

PS: Das Javascript wird auf meiner Website gehostet, aber ich möchte, dass Benutzer das <head>Tag ihrer Website einfügen können, und es sollte in der Lage sein, eine auf meinem Server gehostete CSS-Datei in die aktuelle Webseite zu importieren. (Sowohl die CSS-Datei als auch die Javascript-Datei werden auf meinem Server gehostet).

Klicken Sie auf Upvote
quelle
Es gibt auch Fragen zu jQuery stackoverflow.com/questions/2685614/…
jcubic

Antworten:

416

Hier ist die "alte Schule", die hoffentlich in allen Browsern funktioniert. Theoretisch würden Sie setAttributeIE6 leider nicht konsequent unterstützen.

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

In diesem Beispiel wird überprüft, ob das CSS bereits hinzugefügt wurde, sodass es nur einmal hinzugefügt wird.

Fügen Sie diesen Code in eine Javascript-Datei ein, lassen Sie den Endbenutzer einfach das Javascript einfügen und stellen Sie sicher, dass der CSS-Pfad absolut ist, damit er von Ihren Servern geladen wird.

VanillaJS

Hier ist ein Beispiel, das einfaches JavaScript verwendet, um einen CSS-Link headbasierend auf dem Dateinamen-Teil der URL in das Element einzufügen:

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

Fügen Sie den Code unmittelbar vor dem schließenden headTag ein und das CSS wird geladen, bevor die Seite gerendert wird. Die Verwendung einer externen JavaScript ( .js) - Datei führt dazu, dass ein Flash mit nicht gestylten Inhalten ( FOUC ) angezeigt wird .

card100
quelle
6
Was ist mit einem Rückruf, sobald die CSS-Datei geladen wurde?
Jchook
1
Dies ist viel komplexer und zuverlässig zu erledigen. Die beliebten Javascript-Bibliotheken haben jetzt normalerweise eine Form des Ladens von Javascript und Stylesheets mit einem Rückruf. Ein Beispiel finden Sie unter YUI Get .
9
Vielleicht wäre es besser, ein anderes Zeichen als $ für die Dokumentverknüpfung zu verwenden, da es jQuery leicht stören kann (wie in meinem Fall);)
Zathrus Writer
2
@jonnybojangles Wenn Sie jQuery.noConflict verwenden, müssen Sie alle Ihre Verweise auf jQuery in $ umbenennen. Es wäre viel einfacher, nur einen anderen Variablennamen für den CSS-Loader zu verwenden.
Tommyypyatt
2
@jchook Ich konnte einen Rückruf durch Hinzufügen link.onload = function(){ ... }vor dem Anhängen anhängen
Lounge9
74

Wenn Sie jquery verwenden:

$('head').append('<link rel="stylesheet" type="text/css" href="style.css">');
BoumTAC
quelle
1
Dies funktioniert nur, wenn das Stylesheet vor dem Laden der Seite eingefügt wird, oder? Wenn ich diesen Befehl in der Konsole auf einer geladenen Seite mit einer CSS-Datei ausführe, die ich auf Dropbox gehostet habe, funktioniert er nicht. Irgendeine Idee, wie ich diese Arbeit machen kann:$('head').append('<link rel="stylesheet" type="text/css" href="https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css">');
Thomas
50

Ich denke, so etwas würde dieses Skript tun:

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

Diese JS-Datei enthält die folgende Anweisung:

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

Die Adresse von Javascript und CSS muss absolut sein, wenn sie auf Ihre Site verweisen sollen.

Viele CSS-Importtechniken werden in diesem Artikel "Nein zu CSS-Hacks mit Verzweigungstechniken" erläutert .

Der Artikel "Verwenden von JavaScript zum dynamischen Hinzufügen von Portlet-CSS-Stylesheets" erwähnt jedoch auch die Möglichkeit " CreateStyleSheet" (proprietäre Methode für 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);
}
//]]>
VonC
quelle
Hier ist, was ich document.createStyleSheet()mir ausgedacht habe
Christoph
1
Nicht sicher, in welchem ​​Fall, aber in einigen Fällen, document.writewird nicht empfohlen, da es den gesamten Körper Ihrer Website überschreibt.
Eduard Luca
@VonC, Gibt es eine Funktion, um das <style>Element direkt abzurufen, anstatt anzunehmen, dass es das erste untergeordnete Element von <head>via ist ("head")[0]?
Pacerier
@Pacerier Ich glaube, Sie werden das in groups.google.com/forum/#!topic/prototype-scriptaculous/… beschrieben finden . Das wäre zum Beispiel:var style = document.getElementsByTagName("style")[0];
VonC
20

Element.insertAdjacentHTML bietet eine sehr gute Browserunterstützung und kann ein Stylesheet in einer Zeile hinzufügen.

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

Wenn Sie wissen möchten (oder warten möchten), bis der Stil selbst geladen wurde, funktioniert dies:

// 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);
  });
};
Sandstrom
quelle
Wie benutze ich das
Raj Sharma
Sie würden fetchStyle (url) .then (function () {Zeug geht hier}) über Versprechen
nachlesen
8

Ich weiß, dass dies ein ziemlich alter Thread ist, aber hier kommen meine 5 Cent.

Es gibt eine andere Möglichkeit, dies zu tun, je nachdem, was Ihre Bedürfnisse sind.

Ich habe einen Fall, in dem ich möchte, dass eine CSS-Datei nur eine Weile aktiv ist. Wie CSS-Umschaltung. Aktivieren Sie das CSS und deaktivieren Sie es nach einem anderen Ereignis erneut.

Anstatt das CSS dynamisch zu laden und dann zu entfernen, können Sie eine Klasse / eine ID vor allen Elementen in der neuen CSS hinzufügen und dann einfach diese Klasse / ID des Basisknotens Ihrer CSS wechseln (wie z. B. Body-Tag).

Mit dieser Lösung würden anfangs mehr CSS-Dateien geladen, aber Sie haben eine dynamischere Möglichkeit, CSS-Layouts zu wechseln.

JohanSellberg
quelle
7

In einem modernen Browser können Sie promisedies verwenden. Erstellen Sie eine Laderfunktion mit einem Versprechen darin:

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

Dann möchten Sie natürlich etwas tun, nachdem das CSS geladen wurde. Sie können die Funktion, die ausgeführt werden muss, nachdem CSS geladen wurde, folgendermaßen aufrufen:

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

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

    return DoAfterCSSHasLoaded();
} );

Nützliche Links, wenn Sie genau wissen möchten, wie es funktioniert:

Offizielle Dokumente zu Versprechungen

Nützlicher Leitfaden für Versprechen

Ein großartiges Intro-Video über Versprechen

Arthur Tarasov
quelle
6

Verwenden Sie diesen Code:

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);
Gaurav Tripathi
quelle
4

Es gibt ein allgemeines JQuery-Plugin, das CSS- und JS-Dateien bei Bedarf synchronisieren und asychen lädt. Es verfolgt auch, was bereits geladen wurde :) siehe: http://code.google.com/p/rloader/

ez2
quelle
4

Hier ist ein Weg mit der Elementerstellungsmethode von jQuery (meine Präferenz) und mit dem Rückruf 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);
Lounge9
quelle
3

Die YUI-Bibliothek könnte genau das sein, wonach Sie suchen. Es unterstützt auch das domänenübergreifende Laden.

Wenn Sie jquery verwenden, macht dieses Plugin dasselbe.

anand.trex
quelle
2

Unten ein vollständiger Code zum Laden von JS und / oder 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'])) ();
Hasan A Yousef
quelle
1

Ich möchte eine weitere Möglichkeit nutzen, um nicht nur CSS, sondern alle Assets (JS, CSS, Bilder) zu laden und das Onload- Ereignis für die Reihe von Dateien zu verarbeiten. Es ist async-assets-loader. Siehe das folgende Beispiel:

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

Laut den Async-Assets-Loader- Dokumenten

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

Ich benutze Thymeleaf und das funktioniert gut. Vielen Dank

ekoindra0912
quelle
Was bringt es th:href, auf Client-Seite Attribute hinzuzufügen ? Es wird nicht von Thymeleaf verarbeitet, daher scheint es hier überflüssig zu sein.
Slava Semushin