Come creare un tag <style> con Javascript?


336

Sto cercando un modo per inserire un <style>tag in una pagina HTML con JavaScript.

Il modo migliore che ho trovato finora:

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

Funziona con Firefox, Opera e Internet Explorer ma non con Google Chrome. Inoltre è un po 'brutto con il <br>davanti per IE.

Qualcuno sa un modo per creare un <style>tag che

  1. È più bello

  2. Funziona con Chrome?

O forse

  1. Questa è una cosa non standard che dovrei evitare

  2. Tre browser funzionanti sono fantastici e chi usa Chrome comunque?

Risposte:


663

Prova ad aggiungere l' styleelemento al headanziché al body.

Questo è stato testato in IE (7-9), Firefox, Opera e 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
Cordiali saluti, document.headè supportato in tutti i principali browser.
Rob W,

30
@RobW - Non è supportato in IE8 e versioni successive. È supportato nei browser moderni, ma non in tutti i principali.
Tim

5
perché non usare solo document.querySelector("head")? È l'evento supportato da IE8 dalla fonte
allenhwkim,

8
@allenhwkim: la risposta precede l'introduzione di querySelector(); oggi probabilmente ci andrei document.head, disponibile da IE9
Christoph

2
Prima di accedere ho dovuto aggiungere l'elemento di stile alla testa style.styleSheet.cssText. Prima che fosse aggiunto style.styleSheetera nullo.
Will Hawker,

38

Ecco uno script che aggiunge stile IE createStyleSheet()e addRule()metodi ai browser che non li hanno:

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

È possibile aggiungere file esterni tramite

document.createStyleSheet('foo.css');

e creare dinamicamente regole tramite

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

Questo mi è stato molto utile nel tentativo di caricare un file CSS esterno in uno strano contesto CMS. Ho riscontrato dei problemi con la parte addRule / removeRule, quindi li ho semplicemente eliminati e tutto funziona perfettamente.
Kirkman14,

33

Suppongo che tu voglia inserire un styletag anziché un linktag (facendo riferimento a un CSS esterno), quindi è quello che fa il seguente esempio:

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

Inoltre, ho notato nella tua domanda che stai utilizzando innerHTML. Questo è in realtà un modo non standard di inserire dati in una pagina. La migliore pratica è creare un nodo di testo e accodarlo a un altro nodo di elementi.

Per quanto riguarda la tua domanda finale, sentirai alcune persone dire che il tuo lavoro dovrebbe funzionare su tutti i browser. Tutto dipende dal tuo pubblico. Se nessuno tra il tuo pubblico sta usando Chrome, non farlo sudare; tuttavia, se stai cercando di raggiungere il pubblico più vasto possibile, è meglio supportare tutti i principali browser di livello A.


1
Questo è fondamentalmente lo stesso della mia soluzione; nessuno dei due funziona in IE!
Christoph,

L'aggiunta di un nodo di testo non funziona in Internet Explorer. Ma mettere l'elemento di stile nella testa fa funzionare la mia soluzione in Chrome! :-)

1
per IE, utilizzarestyleNode.styleSheet.cssText = ...
Christoph

7
(Commento molto tardi) "Tutto dipende dal tuo pubblico. Se nessuno tra il tuo pubblico sta usando Chrome, allora non sudare" Questo atteggiamento è ciò che porta le persone a rimanere bloccate in IE6 per anni dopo IE7 e persino IE8 sono disponibili . "Ma l'applicazione web che devo usare funziona solo su IE6"
Stephen P

1
Sì, hai ragione e non sto necessariamente sostenendo di farlo (da qui il tutto: "se stai cercando di raggiungere il pubblico più vasto possibile, allora è meglio supportare tutti i principali browser di livello A") ma conoscendo il il pubblico per la tua piattaforma è importante.
Tom

31

<style>i tag devono essere posti all'interno <head>dell'elemento e ogni tag aggiunto deve essere aggiunto nella parte inferiore del <head>tag.

Utilizzo di insertAdjacentHTML per iniettare un tag di stile nel tag head del documento :

DOM nativo:

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>


D'accordo, è la cosa migliore e semplice ma fai attenzione ai CSS iniettati male se non hai il controllo su di esso!
Infinito

24

Un esempio che funziona e è compatibile con tutti i browser:

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

7
elemento sbagliato: styleha no relo hrefattributo - intendevi link?
Christoph,

4
cosa linkc'entra l'elemento con la domanda? l'OP ha chiesto l' styleelemento. Questa risposta non ha nulla a che fare con la domanda
vsync,

2
@vsync styleè per l'aggiunta di stili incorporati , linkè corretto per le fonti dei fogli di stile e questo ha il vantaggio di evitare problemi tra browser.
Majick,

7

Spesso è necessario sovrascrivere le regole esistenti, quindi aggiungere nuovi stili a HEAD non funziona in tutti i casi.

Mi è venuta in mente questa semplice funzione che riassume tutti gli approcci "append to the BODY" non validi ed è solo più conveniente da usare e eseguire il debug (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


Ha funzionato perfettamente nell'ultimo Firefox, Chrome e in ie8 (o almeno nel modo in cui l'ho digitato). Davvero non so perché questo non abbia più punti.
Harry Pehkonen,

Questo non ha più punti, perché non è valido, né una buona cosa iniettare <style>tag al di fuori del <head>tag. Il tag di stile non dovrebbe apparire in nessun altro posto se non all'interno del <head>tag. Questo è lo standard html ampiamente adottato. Esiste un attributo di stile per lo stile in linea e l'attributo di stile può essere applicato a qualsiasi tag all'interno del <body>tag, incluso il <body>tag stesso.
Spettrale

Questo codice non ha funzionato per me. Ho creato un codice molto più breve che funziona in tre browser e pubblicherò la mia risposta qui.
David Spector,

Non riuscivo a capire perché Chrome non aggiornasse i miei stili quando ho aggiunto dinamicamente un blocco di stile alla testa. Ho provato questo e magicamente si aggiorna. Ho bisogno di indagare quale sia effettivamente la differenza qui in questo codice che attiva il browser per eseguire nuovamente il rendering del CSS. Ma grazie mille!
prograhammer

5

Questa variabile oggetto aggiungerà il tag di stile al tag head con l'attributo type e una semplice regola di transizione all'interno che corrisponde a ogni singolo id / class / element. Sentiti libero di modificare la proprietà del contenuto e di inserire tutte le regole di cui hai bisogno. Assicurati solo che le regole CSS all'interno del contenuto rimangano in una riga (o "scappa" da ogni nuova riga, se preferisci).

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
Mi è piaciuta questa soluzione, quindi l'ho usata io stesso per modificare le dimensioni dei pulsanti sui dispositivi mobili, ma non è corretto che la proprietà del contenuto debba trovarsi su una riga: concatena semplicemente più stringhe (su più righe) con l'operatore +.
RufusVS,

Vero. Lo so e lo sapevo. Ma, a volte, sono troppo pigro per scrivere come dovrei. : D Cin cin.
Spooky

5

Ecco una variante per aggiungere dinamicamente una classe

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

Questa funzione inietterà css ogni volta che la chiamate in appendStylequesto modo:
appendStyle('css you want to inject')

Funziona iniettando un stylenodo nella testa del documento. Questa è una tecnica simile a quella comunemente usata per caricare pigro JavaScript. Funziona costantemente nella maggior parte dei browser moderni.

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>

Puoi anche caricare i file CSS esterni in modo pigro utilizzando il frammento seguente:

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>


Questo è approssimativamente l'approccio che ho sviluppato indipendentemente. Breve e dolce e funziona con gli ultimi browser Firefox, Microsoft Edge e Chrome. Ovviamente, ci sono troppi errori JavaScript in Internet Explorer di cui preoccuparsi di includerlo più nella compatibilità del browser.
David Spector,

3

Hai scritto:

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

Perché non questo?

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

Da quel momento in poi puoi aggiungere facilmente le regole CSS al codice HTML:

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

... o direttamente al DOM:

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

Mi aspetto che funzioni ovunque tranne che nei browser arcaici.

Funziona sicuramente su Chrome nell'anno 2019.


3

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

Di gran lunga la soluzione più semplice. Tutto quello che devi fare è digitare lo stesso di come normalmente dichiareresti i styletag, tra i backtick


1
Ciao e benvenuto nel sito. Sebbene questo codice possa risolvere il problema dato, è necessario includere anche una spiegazione di come e perché funziona.
Radiodef,

1

Se il problema che stai riscontrando è l'iniezione di una stringa di CSS in una pagina, è più facile farlo con l' <link>elemento piuttosto che con l' <style>elemento.

Quanto segue aggiunge la p { color: green; }regola alla pagina.

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

Puoi crearlo in JavaScript semplicemente codificando l'URL della tua stringa di CSS e aggiungendo l' HREFattributo. Molto più semplice di tutte le stranezze degli <style>elementi o dell'accesso diretto ai fogli di stile.

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

Questo funzionerà in IE 5.5 verso l'alto


L'iniezione dinamica del blocco di stile nella testa non ha in alcuni casi aggiornato lo stile. Funziona però!
prograhammer

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.