CSS mit JavaScript zu <head> hinzufügen?

71

Gibt es eine Möglichkeit, CSS aus einer Zeichenfolge in der Javascript-Datei zum Kopf eines Dokuments mit Javascript hinzuzufügen?

Angenommen, wir haben eine Webseite mit einem Lightbox-Skript. Für dieses Skript ist eine CSS-Datei erforderlich.

<link>Wenn Sie nun diese CSS-Datei mit hinzufügen, wird die CSS-Datei auch für Personen heruntergeladen, für die js nicht aktiviert ist.

Ich weiß, dass ich die CSS-Datei dynamisch mit dem Skript laden kann, aber das bedeutet auch, dass es 2 http-Anforderungen gibt, und in Fällen, in denen wenig bis gar kein CSS in der Datei vorhanden ist, finde ich dies ineffizient.

Also dachte ich mir, was wäre, wenn Sie das CSS, das Sie in der CSS-Datei haben, in das Skript einfügen, das Skript das CSS analysieren und in den Kopf einfügen könnten, oder noch besser, das Skript das CSS direkt hinzufügen lassen sollte das <head>des Dokuments.

Aber ich habe online nichts gefunden, was darauf hindeutet, dass dies möglich ist. Ist es also möglich, dem Kopf mit js CSS hinzuzufügen?

Bearbeiten + LÖSUNG:

Ich habe Roryfs Antwort bearbeitet, um browserübergreifend zu arbeiten (außer IE5).

Javascript:

 function addcss(css){
    var head = document.getElementsByTagName('head')[0];
    var s = document.createElement('style');
    s.setAttribute('type', 'text/css');
    if (s.styleSheet) {   // IE
        s.styleSheet.cssText = css;
    } else {                // the world
        s.appendChild(document.createTextNode(css));
    }
    head.appendChild(s);
 }
Timo Huovinen
quelle
1
Werfen Sie einen Blick auf den folgenden Link .. Es erklärt alle kleinen Details zu Ihrer Frage ... und es heißt entsprechend Totally Pwn CSS mit Javascript
Gabriele Petrioli
Verwandte Frage: stackoverflow.com/questions/524696/…
Timo Huovinen

Antworten:

26

Wie möchten Sie <head>mit JavaScript eine CSS-Zeichenfolge hinzufügen ? Wenn Sie eine CSS-Zeichenfolge in eine Seite einfügen, ist dies mit dem <link>Element einfacher als mit dem <style>Element.

Im Folgenden wird p { color: green; }der Seite eine Regel hinzugefügt.

<link rel="stylesheet" type="text/css" href="data:text/css;charset=UTF-8,p%20%7B%20color%3A%20green%3B%20%7D" />

Sie können dies in JavaScript einfach durch URL-Codierung Ihrer CSS-Zeichenfolge und Hinzufügen des HREFAttributs erstellen . Viel einfacher als alle Macken von <style>Elementen oder der direkte Zugriff auf Stylesheets.

var linkElement = this.document.createElement('link');
linkElement.setAttribute('rel', 'stylesheet');
linkElement.setAttribute('type', 'text/css');
linkElement.setAttribute('href', 'data:text/css;charset=UTF-8,' + encodeURIComponent(myStringOfstyles));

Dies funktioniert ab IE 5.5

Die von Ihnen markierte Lösung funktioniert, diese Lösung erfordert jedoch weniger Dom-Operationen und nur ein einziges Element.

Moefinley
quelle
1
let linkElement: HTMLLinkElement = this.document.createElement('link');wird in IE 5.5 funktionieren, sagst du?
Jānis Elmeris
@ JānisElmeris, wenn Sie Javascript mit der von der dh verwendeten Syntax verwenden. createElement und setAttribute sind keine neuen Methoden.
Bogdan M.
@BogdanM. Nun, ich erwarte nur, dass der als "das wird funktionieren in ..." beschriebene Code tatsächlich bereits die richtige Syntax hat.
Jānis Elmeris
let linkElement: HTMLLinkElement = ...- Wie heißt diese Syntax?
Scott Martin
Entschuldigung, das ist ein Typescript-Typ. Es sollte eigentlich nicht da drin sein.
Moefinley
31

Bearbeiten : Wie der Kommentar von Atspulgs andeutet, können Sie dasselbe ohne jQuery mit dem querySelector erreichen :

document.querySelector('head').innerHTML += '<link rel="stylesheet" href="styles.css" type="text/css"/>';

Ältere Antwort unten.


Mit der jQuery- Bibliothek können Sie Ihr head-Element auswählen und HTML anhängen, und zwar auf folgende Weise:

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

Ein vollständiges Tutorial zu diesem Problem finden Sie hier

thomaux
quelle
4
Auch diese Methode lädt eine neue Datei, die Yuri vermeiden wollte. Außerdem ist es ziemlich dumm, die gesamte jQuery-Bibliothek für etwas so Einfaches wie dieses zu laden.
TRiG
4
ohne jQuery: document.querySelector ('head'). innerHTML + = '<link rel = "stylesheet" href = "styles.css" type = "text / css" />';
Atspulgs
3
document.headist das headElement!
Iharob Al Asimi
26

Wenn Sie sich nicht auf eine Javascript-Bibliothek verlassen möchten, können Sie document.write()das erforderliche CSS, das in styleTags verpackt ist , direkt in das Dokument ausspucken head:

<head>
  <script type="text/javascript">
    document.write("<style>body { background-color:#000 }</style>");
  </script>
  # other stuff..
</head>

Auf diese Weise vermeiden Sie das Auslösen einer zusätzlichen HTTP-Anforderung.

Es gibt andere Lösungen, die vorgeschlagen / hinzugefügt / entfernt wurden, aber ich sehe keinen Grund darin, etwas zu komplizieren, das bereits browserübergreifend funktioniert. Viel Glück!

http://jsbin.com/oqede3/edit

Jeriko
quelle
13
Dies ist in Ordnung, bis Sie nach dem Rendern des Dokuments eine CSS-Regel hinzufügen möchten.
Tim Down
Gut, dass OP diese Anforderung dann nicht hat! Ihre Lösung deckt das ab, aber imho ist es für Over-JS / Lightbox-CSS-Verschlechterung völlig übertrieben.
Jeriko
2
Eines ist zu beachten: Funktioniert document.writenicht in echten XHTML-Dokumenten, aber das ist wahrscheinlich kein Problem, da kaum jemand XHTML wirklich verwendet.
Tim Down
Es ist interessant, dass es funktioniert, aber Stil im Körper zu haben, sieht ein bisschen hacky aus :) ps Sie können das document.write in den Kopfbereich der Site einfügen und es scheint gut zu funktionieren.
Timo Huovinen
1
Ich würde document.write so weit wie möglich vermeiden.
Orcra
14

Eine einfache Nicht-jQuery-Lösung, wenn auch mit einem kleinen Hack für den IE:

var css = ".lightbox { width: 400px; height: 400px; border: 1px solid #333}";

var htmlDiv = document.createElement('div');
htmlDiv.innerHTML = '<p>foo</p><style>' + css + '</style>';
document.getElementsByTagName('head')[0].appendChild(htmlDiv.childNodes[1]);

Es scheint IE erlaubt keine Einstellung innerText, innerHTMLoder die Verwendung appendChildauf styleElemente. Hier ist ein Fehlerbericht, der dies demonstriert, obwohl ich denke, dass er das Problem falsch identifiziert. Die obige Problemumgehung stammt aus den Kommentaren zum Fehlerbericht und wurde in IE6 und IE9 getestet.

Ob Sie dies, document.write oder eine komplexere Lösung verwenden, hängt wirklich von Ihrer Situation ab.

roryf
quelle
Funktioniert nicht im IE. Sicherlich nicht 6 oder 7, es stehen momentan keine 8 zum Testen zur Verfügung. IE mag nicht document.createElement('style').
Tim Down
@ Tim funktioniert für mich in IE6 und 9, da Ihre Lösung genau die gleiche Zeile hat, können Sie vielleicht weiter erklären
Roryf
@roryf: Oh ja, du hast recht, sorry. Dummerweise habe ich den elementaren Fehler gemacht, die Zeilennummer in den Fehler des IE zu glauben. Der Fehler ist tatsächlich in styleElement.innerHTML = css;. Sicherlich schlägt dies in IE 7 fehl und wird jetzt in IE 6 erneut getestet (wartet darauf, dass die VM lebendig wird).
Tim Down
@ Tim danke, ich vermutete, dass das ein Problem sein könnte, schade für mich, dass ich nicht richtig getestet habe!
Roryf
2
Ich konnte dies nicht alleine lassen, also habe ich ein bisschen recherchiert und eine Problemumgehung für den
Internet
9

Hier ist eine Funktion, die dynamisch eine CSS-Regel in allen gängigen Browsern erstellt. createCssRuleNimmt einen Selektor (zB "p.purpleText"), eine Regel (zB "Farbe: lila;") und optional a Document(das aktuelle Dokument wird standardmäßig verwendet):

var addRule;

if (typeof document.styleSheets != "undefined" && document.styleSheets) {
    addRule = function(selector, rule) {
        var styleSheets = document.styleSheets, styleSheet;
        if (styleSheets && styleSheets.length) {
            styleSheet = styleSheets[styleSheets.length - 1];
            if (styleSheet.addRule) {
                styleSheet.addRule(selector, rule)
            } else if (typeof styleSheet.cssText == "string") {
                styleSheet.cssText = selector + " {" + rule + "}";
            } else if (styleSheet.insertRule && styleSheet.cssRules) {
                styleSheet.insertRule(selector + " {" + rule + "}", styleSheet.cssRules.length);
            }
        }
    }
} else {
    addRule = function(selector, rule, el, doc) {
        el.appendChild(doc.createTextNode(selector + " {" + rule + "}"));
    };
}

function createCssRule(selector, rule, doc) {
    doc = doc || document;
    var head = doc.getElementsByTagName("head")[0];
    if (head && addRule) {
        var styleEl = doc.createElement("style");
        styleEl.type = "text/css";
        styleEl.media = "screen";
        head.appendChild(styleEl);
        addRule(selector, rule, styleEl, doc);
        styleEl = null;
    }
};

createCssRule("body", "background-color: purple;");
Tim Down
quelle
Sehr gründliche Antwort, und ich glaube, es wird nützlich sein, aber es wird mühsam sein, ein einfaches CSS-Stylesheet zu nehmen und es in dieses zu konvertieren.
Timo Huovinen
5

Hier ist ein einfacher Weg.

/**
 * Add css to the document
 * @param {string} css
 */
function addCssToDocument(css){
  var style = document.createElement('style')
  style.innerText = css
  document.head.appendChild(style)
}
Verbündete
quelle