Wie erstelle ich ein <style> -Tag mit Javascript?

336

Ich suche nach einer Möglichkeit, ein <style>Tag mit JavaScript in eine HTML-Seite einzufügen .

Der beste Weg, den ich bisher gefunden habe:

var divNode = document.createElement("div");
divNode.innerHTML = "<br><style>h1 { background: red; }</style>";
document.body.appendChild(divNode);

Dies funktioniert in Firefox, Opera und Internet Explorer, jedoch nicht in Google Chrome. Auch ist es ein bisschen hässlich mit dem <br>vorne für IE.

Kennt jemand eine Möglichkeit, ein <style>Tag zu erstellen , das

  1. Ist schöner

  2. Funktioniert mit Chrome?

Oder vielleicht

  1. Dies ist eine nicht standardmäßige Sache, die ich vermeiden sollte

  2. Drei funktionierende Browser sind großartig und wer nutzt Chrome überhaupt?

Ameena Sana
quelle

Antworten:

663

Versuchen Sie, das styleElement dem headstatt dem hinzuzufügen body.

Dies wurde in IE (7-9), Firefox, Opera und Chrome getestet:

var css = 'h1 { background: red; }',
    head = document.head || document.getElementsByTagName('head')[0],
    style = document.createElement('style');

head.appendChild(style);

style.type = 'text/css';
if (style.styleSheet){
  // This is required for IE8 and below.
  style.styleSheet.cssText = css;
} else {
  style.appendChild(document.createTextNode(css));
}
Christoph
quelle
19
FYI document.headwird in allen gängigen Browsern unterstützt.
Rob W
30
@RobW - Es wird in IE8 und darunter nicht unterstützt. Es wird in modernen Browsern unterstützt, aber nicht in allen wichtigen.
Tim
5
warum nicht einfach benutzen document.querySelector("head")? Es ist Ereignis von IE8 von Quelle unterstützt
Allenhwkim
8
@allenhwkim: Die Antwort ist älter als die Einführung von querySelector(); Heute würde ich wahrscheinlich mitgehen document.head, verfügbar seit IE9
Christoph
2
Ich musste das Stilelement vor dem Zugriff an den Kopf anhängen style.styleSheet.cssText. Vor dem Anhängen style.styleSheetwar null.
Will Hawker
38

Hier ist ein Skript, das Browsern, die diese nicht haben, IE-Stil createStyleSheet()und addRule()Methoden hinzufügt :

if(typeof document.createStyleSheet === 'undefined') {
    document.createStyleSheet = (function() {
        function createStyleSheet(href) {
            if(typeof href !== 'undefined') {
                var element = document.createElement('link');
                element.type = 'text/css';
                element.rel = 'stylesheet';
                element.href = href;
            }
            else {
                var element = document.createElement('style');
                element.type = 'text/css';
            }

            document.getElementsByTagName('head')[0].appendChild(element);
            var sheet = document.styleSheets[document.styleSheets.length - 1];

            if(typeof sheet.addRule === 'undefined')
                sheet.addRule = addRule;

            if(typeof sheet.removeRule === 'undefined')
                sheet.removeRule = sheet.deleteRule;

            return sheet;
        }

        function addRule(selectorText, cssText, index) {
            if(typeof index === 'undefined')
                index = this.cssRules.length;

            this.insertRule(selectorText + ' {' + cssText + '}', index);
        }

        return createStyleSheet;
    })();
}

Sie können externe Dateien über hinzufügen

document.createStyleSheet('foo.css');

und dynamisch Regeln erstellen über

var sheet = document.createStyleSheet();
sheet.addRule('h1', 'background: red;');
Christoph
quelle
Dies war sehr hilfreich für mich beim Versuch, eine externe CSS-Datei in einem seltsamen CMS-Kontext zu laden. Ich hatte einige Probleme mit dem Teil addRule / removeRule, also habe ich diese nur beseitigt, und alles funktioniert einwandfrei.
Kirkman14
33

Ich gehe davon aus, dass Sie ein styleTag im Vergleich zu einem linkTag einfügen möchten (unter Bezugnahme auf ein externes CSS). Das ist also das folgende Beispiel:

<html>
 <head>
  <title>Example Page</title>
 </head>
 <body>
  <span>
   This is styled dynamically via JavaScript.
  </span>
 </body>
 <script type="text/javascript">
   var styleNode = document.createElement('style');
   styleNode.type = "text/css";
   // browser detection (based on prototype.js)
   if(!!(window.attachEvent && !window.opera)) {
        styleNode.styleSheet.cssText = 'span { color: rgb(255, 0, 0); }';
   } else {
        var styleText = document.createTextNode('span { color: rgb(255, 0, 0); } ');
        styleNode.appendChild(styleText);
   }
   document.getElementsByTagName('head')[0].appendChild(styleNode);
 </script>
</html>

Außerdem habe ich in Ihrer Frage festgestellt, dass Sie verwenden innerHTML. Dies ist eigentlich eine nicht standardmäßige Methode zum Einfügen von Daten in eine Seite. Am besten erstellen Sie einen Textknoten und hängen ihn an einen anderen Elementknoten an.

In Bezug auf Ihre letzte Frage werden Sie einige Leute sagen hören, dass Ihre Arbeit in allen Browsern funktionieren sollte. Es hängt alles von Ihrem Publikum ab. Wenn niemand in Ihrer Zielgruppe Chrome verwendet, schwitzen Sie nicht. Wenn Sie jedoch das größtmögliche Publikum erreichen möchten, ist es am besten, alle gängigen Browser der Klasse A zu unterstützen

Tom
quelle
1
Dies ist im Grunde das gleiche wie meine Lösung; Keiner von ihnen funktioniert im IE!
Christoph
Das Anhängen eines Textknotens funktioniert im IE nicht. Aber wenn ich das Stilelement in den Kopf setze, funktioniert meine Lösung in Chrome! :-)
1
für IE verwendenstyleNode.styleSheet.cssText = ...
Christoph
7
(Sehr später Kommentar) "Es hängt alles von Ihrer Zielgruppe ab. Wenn niemand in Ihrer Zielgruppe Chrome verwendet, schwitzen Sie nicht." Diese Einstellung führt dazu, dass Personen jahrelang an IE6 gebunden sind, nachdem IE7 und sogar IE8 verfügbar sind . "Aber die Webanwendung, die ich verwenden muss, funktioniert nur in IE6"
Stephen P
1
Ja, Sie haben Recht und ich befürworte dies auch nicht unbedingt (daher das Ganze: "Wenn Sie das größtmögliche Publikum erreichen möchten, ist es am besten, alle gängigen Browser der Klasse A zu unterstützen"), aber Sie kennen das Das Publikum für Ihre Plattform ist wichtig.
Tom
31

<style>Tags sollten Stellen innerhalb des <head>Elements sein, und jedes hinzugefügte Tag sollte am unteren Rand des <head>Tags hinzugefügt werden .

Verwenden von insertAdjacentHTML zum Einfügen eines Stil-Tags in das Dokumentkopf- Tag :

Native DOM:

document.head.insertAdjacentHTML("beforeend", `<style>body{background:red}</style>`)


jQuery :

$('<style>').text("body{background:red}").appendTo(document.head)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

vsync
quelle
2
Dies ist die beste und einfachste Lösung, danke!
Ryzal Yusoff
Stimmen Sie zu, es ist am besten und einfach, aber achten Sie auf schlecht injiziertes CSS, wenn Sie nicht die Kontrolle darüber haben!
Endlos
24

Ein Beispiel, das funktioniert und mit allen Browsern kompatibel ist:

var ss = document.createElement("link");
ss.type = "text/css";
ss.rel = "stylesheet";
ss.href = "style.css";
document.getElementsByTagName("head")[0].appendChild(ss);
belaz
quelle
7
falsches Element: stylehat kein reloder hrefAttribut - meintest du link?
Christoph
4
Was hat linkElement mit der Frage zu tun? Das OP fragte nach einem styleElement. Diese Antwort hat nichts mit der Frage zu tun
vsync
2
@vsync styledient zum Hinzufügen von Inline-Stilen, linkist für Stylesheet-Quellen korrekt und hat den Vorteil, dass browserübergreifende Probleme vermieden werden.
Majick
7

Oft müssen vorhandene Regeln überschrieben werden, sodass das Anhängen neuer Stile an den HEAD nicht in jedem Fall funktioniert.

Ich habe mir diese einfache Funktion ausgedacht , die alle ungültigen Ansätze zum Anhängen an den KÖRPER zusammenfasst und einfach bequemer zu verwenden und zu debuggen ist (IE8 +).

window.injectCSS = (function(doc){
    // wrapper for all injected styles and temp el to create them
    var wrap = doc.createElement('div');
    var temp = doc.createElement('div');
    // rules like "a {color: red}" etc.
    return function (cssRules) {
        // append wrapper to the body on the first call
        if (!wrap.id) {
            wrap.id = 'injected-css';
            wrap.style.display = 'none';
            doc.body.appendChild(wrap);
        }
        // <br> for IE: http://goo.gl/vLY4x7
        temp.innerHTML = '<br><style>'+ cssRules +'</style>';
        wrap.appendChild( temp.children[1] );
    };
})(document);

Demo: Codepen , Jsfiddle

Garlaro
quelle
Funktionierte perfekt in den neuesten Versionen von Firefox, Chrome und IE8 (oder zumindest so, wie ich es eingegeben habe). Ich weiß wirklich nicht, warum das nicht mehr Punkte hat.
Harry Pehkonen
Dies hat keine Punkte mehr, da es nicht gültig ist und es auch nicht gut ist, ein <style>Tag außerhalb des <head>Tags zu injizieren . Das Style-Tag sollte nur innerhalb des <head>Tags angezeigt werden. Das ist ein weit verbreiteter HTML-Standard. Es gibt ein Stilattribut für das Inline-Styling und das Stilattribut kann auf jedes Tag innerhalb des <body>Tags angewendet werden , einschließlich des <body>Tags selbst.
Spooky
Dieser Code hat bei mir nicht funktioniert. Ich habe einen viel kürzeren Code erstellt, der in drei Browsern funktioniert, und werde meine Antwort hier veröffentlichen.
David Spector
Ich konnte nicht herausfinden, warum Chrome meine Stile nicht aktualisiert hat, als ich dem Kopf dynamisch einen Stilblock hinzufügte. Ich habe es versucht und es wird auf magische Weise aktualisiert. Ich muss untersuchen, was hier in diesem Code tatsächlich der Unterschied ist, der den Browser dazu veranlasst, das CSS neu zu rendern. Aber vielen Dank!
Programmierer
5

Diese Objektvariable hängt ein Style-Tag mit einem Typattribut und einer einfachen Übergangsregel an das Head-Tag an, die mit jeder einzelnen ID / Klasse / Element übereinstimmt. Sie können die Inhaltseigenschaft jederzeit ändern und so viele Regeln einfügen, wie Sie benötigen. Stellen Sie einfach sicher, dass die CSS-Regeln im Inhalt in einer Zeile bleiben (oder "Escape" jeder neuen Zeile, wenn Sie dies bevorzugen).

var script = {

  type: 'text/css', style: document.createElement('style'), 
  content: "* { transition: all 220ms cubic-bezier(0.390, 0.575, 0.565, 1.000); }",
  append: function() {

    this.style.type = this.type;
    this.style.appendChild(document.createTextNode(this.content));
    document.head.appendChild(this.style);

}}; script.append();
Gruslig
quelle
1
Diese Lösung hat mir gefallen, daher habe ich sie selbst verwendet, um die Tastengröße auf Mobilgeräten zu ändern. Es ist jedoch falsch, dass sich die Inhaltseigenschaft in einer Zeile befinden muss: Verketten Sie einfach mehrere Zeichenfolgen (über mehrere Zeilen) mit dem Operator +.
RufusVS
Wahr. Ich weiß und ich wusste das. Aber manchmal bin ich einfach zu faul, um so zu schreiben, wie ich soll. : D Prost.
Spooky
5

Hier ist eine Variante zum dynamischen Hinzufügen einer Klasse

function setClassStyle(class_name, css) {
  var style_sheet = document.createElement('style');
  if (style_sheet) {
    style_sheet.setAttribute('type', 'text/css');
    var cstr = '.' + class_name + ' {' + css + '}';
    var rules = document.createTextNode(cstr);
    if(style_sheet.styleSheet){// IE
      style_sheet.styleSheet.cssText = rules.nodeValue;
    } else {
      style_sheet.appendChild(rules);
    }
    var head = document.getElementsByTagName('head')[0];
    if (head) {
      head.appendChild(style_sheet);
    }
  }
}
Michael
quelle
4

Diese Funktion injiziert CSS, wenn Sie die Funktion appendStylewie folgt aufrufen :
appendStyle('css you want to inject')

Dies funktioniert durch Einfügen eines styleKnotens in den Kopf des Dokuments. Dies ist eine ähnliche Technik wie beim langsamen Laden von JavaScript. Es funktioniert konsistent in den meisten modernen Browsern.

appendStyle = function (content) {
  style = document.createElement('STYLE');
  style.type = 'text/css';
  style.appendChild(document.createTextNode(content));
  document.head.appendChild(style);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
  <h1>Lorem Ipsum</h1>
  <p>dolar sit amet</p>
  <button onclick='appendStyle("body { background-color: #ff0000;}h1 { font-family: Helvetica, sans-serif; font-variant: small-caps; letter-spacing: 3px; color: #ff0000; background-color: #000000;}p { font-family: Georgia, serif; font-size: 14px; font-style: normal; font-weight: normal; color: #000000; background-color: #ffff00;}")'>Press me to inject CSS!</button>
</body>

</html>

Sie können auch externe CSS-Dateien mithilfe des folgenden Snippets verzögert laden:

appendExternalStyle = function (content) {
  link = document.createElement('LINK');
  link.rel = 'stylesheet';
  link.href = content;
  link.type = 'text/css';
  document.head.appendChild(link);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    html {
      font-family: sans-serif;
      font-display: swap;
    }
  </style>
</head>

<body>

  <h1>Lorem Ipsum</h1>
  <p>dolar sit amet</p>
  <button onclick='appendExternalStyle("data:text/css;base64,OjotbW96LXNlbGVjdGlvbntjb2xvcjojZmZmIWltcG9ydGFudDtiYWNrZ3JvdW5kOiMwMDB9OjpzZWxlY3Rpb257Y29sb3I6I2ZmZiFpbXBvcnRhbnQ7YmFja2dyb3VuZDojMDAwfWgxe2ZvbnQtc2l6ZToyZW19Ym9keSxodG1se2NvbG9yOnJnYmEoMCwwLDAsLjc1KTtmb250LXNpemU6MTZweDtmb250LWZhbWlseTpMYXRvLEhlbHZldGljYSBOZXVlLEhlbHZldGljYSxzYW5zLXNlcmlmO2xpbmUtaGVpZ2h0OjEuNjd9YnV0dG9uLGlucHV0e292ZXJmbG93OnZpc2libGV9YnV0dG9uLHNlbGVjdHstd2Via2l0LXRyYW5zaXRpb24tZHVyYXRpb246LjFzO3RyYW5zaXRpb24tZHVyYXRpb246LjFzfQ==")'>press me to inject css!</button>
</body>

</html>

Joel Ellis
quelle
Dies ist ungefähr der Ansatz, den ich unabhängig entwickelt habe. Kurz und bündig und funktioniert in den neuesten Firefox-, Microsoft Edge- und Chrome-Browsern. Natürlich gibt es in Internet Explorer zu viele JavaScript-Fehler, um sie nicht mehr in die Browserkompatibilität aufzunehmen.
David Spector
3

Sie schrieben:

var divNode = document.createElement("div");
divNode.innerHTML = "<br><style>h1 { background: red; }</style>";
document.body.appendChild(divNode);

Warum nicht das?

var styleNode = document.createElement("style");
document.head.appendChild(styleNode);

Von nun an können Sie CSS-Regeln einfach an den HTML-Code anhängen:

styleNode.innerHTML = "h1 { background: red; }\n";
styleNode.innerHTML += "h2 { background: green; }\n";

... oder direkt zum DOM:

styleNode.sheet.insertRule("h1 { background: red; }");
styleNode.sheet.insertRule("h2 { background: green; }");

Ich erwarte, dass dies überall funktioniert, außer in archaischen Browsern.

Funktioniert definitiv in Chrome im Jahr 2019.

7vujy0f0hy
quelle
3

document.head.innerHTML += `
  <style>
    h1 {
      color: red; 
    }
    p {
      color: blue;
    }
  </style>`
<h1>I'm red!</h1>
<p>I'm blue!</p>

Mit Abstand die einfachste Lösung. Alles, was Sie tun müssen, ist style, zwischen den Backticks dasselbe einzugeben, wie Sie normalerweise Tags deklarieren würden

Kabirr singh sahni
quelle
1
Hallo und willkommen auf der Seite. Während dieser Code das gegebene Problem lösen kann, sollten Sie auch eine Erklärung hinzufügen, wie und warum es funktioniert.
Radiodef
1

Wenn das Problem darin besteht, eine CSS-Zeichenfolge in eine Seite einzufü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.

let linkElement: HTMLLinkElement = 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 in IE 5.5 abwärts

Moefinley
quelle
Das dynamische Injizieren des Stilblocks in den Kopf hat das Styling in einigen Fällen nicht aktualisiert. Das funktioniert aber!
Programmierer
-1
this link may helpful to you: 

http://jonraasch.com/blog/javascript-style-node

Vinod Poorma
quelle
Bitte verwenden Sie keine vorformatierten Text- / Codeblöcke für einen kurzen Absatz. Das Verknüpfen für eine Antwort auf diese Weise ist ebenfalls nutzlos. Bitte fassen Sie zuerst die Website zusammen.
FryingggPannn