Jak utworzyć tag <style> za pomocą Javascript?


336

Szukam sposobu na wstawienie <style>tagu na stronie HTML za pomocą JavaScript.

Najlepszy sposób, jaki do tej pory znalazłem:

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

Działa to w Firefox, Opera i Internet Explorer, ale nie w Google Chrome. Jest też trochę brzydki z <br>przodu dla IE.

Czy ktoś wie, jak stworzyć taki <style>tag

  1. Jest milszy

  2. Działa z Chrome?

Albo może

  1. To jest niestandardowa rzecz, której powinienem unikać

  2. Trzy działające przeglądarki są świetne i kto i tak używa Chrome?

Odpowiedzi:


663

Spróbuj dodać styleelement headzamiast do body.

Zostało to przetestowane w IE (7-9), Firefox, Opera i Chrome:

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

19
FYI document.headjest obsługiwany we wszystkich głównych przeglądarkach.
— Rob W

30
@RobW - Nie jest obsługiwany w IE8 i niższych wersjach. Jest obsługiwany w nowoczesnych przeglądarkach, ale nie we wszystkich głównych.
— Tim

5
dlaczego nie po prostu użyć document.querySelector("head")? To wydarzenie obsługiwane przez IE8 według źródła
— allenhwkim

8
@allenhwkim: odpowiedź poprzedza wprowadzenie querySelector(); dziś prawdopodobnie wybrałbym z document.head, dostępny od IE9
— Christoph

2
Musiałem dołączyć element stylu do głowy przed uzyskaniem dostępu style.styleSheet.cssText. Przed dołączeniem style.styleSheetbył zerowy.
— Will Hawker,

38

Oto skrypt, który dodaje style IE createStyleSheet()i addRule()metody do przeglądarek, które ich nie mają:

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

Możesz dodać pliki zewnętrzne za pośrednictwem

document.createStyleSheet('foo.css');

i dynamicznie twórz reguły poprzez

var sheet = document.createStyleSheet();
sheet.addRule('h1', 'background: red;');

Pomogło mi to w załadowaniu zewnętrznego pliku CSS w dziwnym kontekście CMS. Miałem pewne problemy z częścią addRule / removeRule, więc po prostu je wyeliminowałem i wszystko działa dobrze.
— Kirkman14,

33

Zakładam, że chcesz wstawić styletag w porównaniu do linktagu (odwołując się do zewnętrznego CSS), więc to właśnie robi następujący przykład:

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

Zauważyłem też w twoim pytaniu, że używasz innerHTML. Jest to w rzeczywistości niestandardowy sposób wstawiania danych na stronę. Najlepszą praktyką jest utworzenie węzła tekstowego i dołączenie go do innego węzła elementu.

Jeśli chodzi o twoje ostatnie pytanie, usłyszysz, jak niektórzy mówią, że twoja praca powinna działać we wszystkich przeglądarkach. Wszystko zależy od odbiorców. Jeśli nikt z Twoich odbiorców nie używa Chrome, nie przejmuj się; Jeśli jednak chcesz dotrzeć do jak największej liczby odbiorców, najlepiej jest obsługiwać wszystkie główne przeglądarki klasy A.


1
Jest to w zasadzie to samo, co moje rozwiązanie; żadne z nich nie działa w IE!
— Christoph

Dołączenie węzła tekstowego nie działa w IE. Ale umieszczenie elementu stylu w głowie sprawia, że ​​moje rozwiązanie działa w Chrome! :-)

1
dla IE użyjstyleNode.styleSheet.cssText = ...
— Christoph

7
(Bardzo późny komentarz) „Wszystko zależy od odbiorców. Jeśli nikt z odbiorców nie korzysta z Chrome, nie przejmuj się” Takie podejście prowadzi do zablokowania ludzi w IE6 przez lata po udostępnieniu IE7, a nawet IE8 . „Ale aplikacja internetowa, z której muszę korzystać, działa tylko w IE6”
— Stephen P

1
Tak, masz rację i niekoniecznie zalecam robienie tego (stąd całość: „jeśli chcesz dotrzeć do jak największej liczby odbiorców, najlepiej jest obsługiwać wszystkie główne przeglądarki klasy A”), ale znając publiczność na Twojej platformie jest ważna.
— Tom

31

<style>tagi powinny być miejscami wewnątrz <head>elementu, a każdy dodany tag powinien być dodany na dole <head>tagu.

Używanie insertAdjacentHTML do wstrzykiwania znacznika stylu do znacznika nagłówka dokumentu :

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


Zgadzam się, jest to najlepsze i proste, ale uważaj na źle wstrzyknięty css, jeśli nie masz nad nim kontroli!
— Endless

24

Przykład, który działa i jest zgodny ze wszystkimi przeglądarkami:

var ss = document.createElement("link");
ss.type = "text/css";
ss.rel = "stylesheet";
ss.href = "style.css";
document.getElementsByTagName("head")[0].appendChild(ss);

7
zły element: stylenie ma rellub ma hrefatrybut - miałeś na myśli link?
— Christoph

4
co linkma wspólnego element z pytaniem? OP poprosił o styleelement. Ta odpowiedź nie ma nic wspólnego z pytaniem
— vsync,

2
@vsync stylesłuży do dodawania stylów wbudowanych, linkjest poprawny dla źródeł arkuszy stylów i ma tę zaletę, że pozwala uniknąć problemów w różnych przeglądarkach.
— majick 12.04.16

7

Często trzeba zastąpić istniejące reguły, więc dołączanie nowych stylów do HEAD nie zawsze działa.

Wymyśliłem tę prostą funkcję, która podsumowuje wszystkie niepoprawne podejścia „dołącz do BODY” i jest po prostu wygodniejsza w użyciu i debugowaniu (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


Doskonale działał w najnowszym Firefoksie, Chrome i ie8 (a przynajmniej tak, jak go wpisałem). Naprawdę nie wiem, dlaczego to nie ma więcej punktów.
— Harry Pehkonen,

Nie ma to już więcej punktów, ponieważ nie jest poprawne, ani dobrą rzeczą do wstrzykiwania <style>tagu poza <head>tag. Tag stylu nie powinien pojawiać się nigdzie indziej niż w <head>tagu. To powszechnie przyjęty standard HTML. Istnieje atrybut stylu dla wbudowanego stylu, a atrybut stylu może być zastosowany do dowolnego znacznika w <body>znaczniku, w tym <body>znacznika.
— Spooky

Ten kod nie działał dla mnie. Stworzyłem trochę krótszy kod, który działa w trzech przeglądarkach i opublikuję tutaj swoją odpowiedź.
— David Spector,

Nie mogłem zrozumieć, dlaczego Chrome nie aktualizował moich stylów, gdy dynamicznie dodawałem blok stylów do głowy. Próbowałem tego i magicznie aktualizuje się. Muszę zbadać, jaka jest tutaj różnica w tym kodzie, która powoduje, że przeglądarka ponownie renderuje css. Ale wielkie dzięki!
— prograhammer

5

Ta zmienna obiektowa doda tag stylu do tagu head z atrybutem type i jedną prostą regułą przejścia wewnątrz, która pasuje do każdego identyfikatora / klasy / elementu. Możesz modyfikować właściwości treści i wprowadzać tyle reguł, ile potrzebujesz. Po prostu upewnij się, że reguły css wewnątrz zawartości pozostają w jednym wierszu (lub „uciekaj” z każdego nowego wiersza, jeśli wolisz).

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

1
Podobało mi się to rozwiązanie, więc sam go użyłem do zmiany rozmiarów przycisków na urządzeniach mobilnych, ale niepoprawne jest to, że właściwość content musi znajdować się w jednym wierszu: po prostu połącz wiele ciągów (w wielu wierszach) z operatorem +.
— RufusVS,

Prawdziwe. Wiem i wiedziałem o tym. Ale czasami jestem zbyt leniwy, by pisać tak, jak powinienem. : D Na zdrowie.
— Spooky

5

Oto wariant dynamicznego dodawania klasy

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


4

Ta funkcja wstrzykuje css za każdym razem, gdy wywołasz funkcję w appendStylenastępujący sposób:
appendStyle('css you want to inject')

Działa to poprzez wstrzyknięcie stylewęzła do nagłówka dokumentu. Jest to technika podobna do powszechnie używanej do leniwego ładowania JavaScript. Działa konsekwentnie w większości nowoczesnych przeglądarek.

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>

Możesz także leniwie ładować zewnętrzne pliki CSS, używając następującego fragmentu:

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>


Jest to z grubsza podejście, które opracowałem niezależnie. Krótkie i słodkie i działa w najnowszych przeglądarkach Firefox, Microsoft Edge i Chrome. Oczywiście w przeglądarce Internet Explorer jest zbyt wiele błędów JavaScript, aby martwić się o włączenie jej do zgodności z przeglądarką.
— David Spector,

3

Napisałeś:

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

Dlaczego nie to

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

Odtąd możesz łatwo dołączać reguły CSS do kodu HTML:

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

... lub bezpośrednio do DOM:

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

Spodziewam się, że zadziała to wszędzie oprócz archaicznych przeglądarek.

Zdecydowanie działa w Chrome w roku 2019.


3

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

Zdecydowanie najprostsze rozwiązanie. Wszystko, co musisz zrobić, to wpisać to samo, co normalnie deklarujesz styletagi, pomiędzy backtickami


1
Witam i witam na stronie. Chociaż ten kod może rozwiązać dany problem, należy również wyjaśnić, w jaki sposób i dlaczego to działa.
— Radiodef,

1

Jeśli napotykasz problem polegający na wstrzykiwaniu ciągu CSS na stronę, łatwiej jest to zrobić z <link>elementem niż z <style>elementem.

Poniżej dodano p { color: green; }regułę do strony.

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

Możesz utworzyć to w JavaScript po prostu przez kodowanie URL-a łańcucha CSS i dodanie go do HREFatrybutu. Znacznie prostsze niż wszystkie dziwactwa <style>elementów lub bezpośredni dostęp do arkuszy stylów.

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

Będzie to działać w IE 5.5 w górę


Dynamiczne wstrzykiwanie bloku stylu w głowę nie aktualizowało stylu w niektórych przypadkach. To działa!
— prograhammer

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.