How to create a <style> tag with Javascript?

JavascriptHtmlCss

Javascript Problem Overview


I'm looking for a way to insert a <style> tag into an HTML page with JavaScript.

The best way I found so far:

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

This works in Firefox, Opera and Internet Explorer but not in Google Chrome. Also it's a bit ugly with the <br> in front for IE.

Does anyone know of a way to create a <style> tag that

  1. Is nicer

  2. Works with Chrome?

Or maybe

  1. This is a non-standard thing I should avoid

  2. Three working browsers are great and who uses Chrome anyway?

Javascript Solutions


Solution 1 - Javascript

Try adding the style element to the head rather than the body.

This was tested in IE (7-9), Firefox, Opera and 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));
}

Solution 2 - Javascript

<style> tags should be placed within the <head> element, and each added tag should be added to the bottom of the <head> tag.

Using insertAdjacentHTML to inject a style tag into the document head 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>

Solution 3 - Javascript

I'm assuming that you're wanting to insert a style tag versus a link tag (referencing an external CSS), so that's what the following example does:

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

Also, I noticed in your question that you are using innerHTML. This is actually a non-standard way of inserting data into a page. The best practice is to create a text node and append it to another element node.

With respect to your final question, you're going to hear some people say that your work should work across all of the browsers. It all depends on your audience. If no one in your audience is using Chrome, then don't sweat it; however, if you're looking to reach the biggest audience possible, then it's best to support all major A-grade browsers

Solution 4 - Javascript

Here's a script which adds IE-style createStyleSheet() and addRule() methods to browsers which don't have them:

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

You can add external files via

document.createStyleSheet('foo.css');

and dynamically create rules via

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

Solution 5 - Javascript

An example that works and are compliant with all browsers :

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

Solution 6 - Javascript

const style = document.createElement("style")
style.textContent = "h1 { background-color: red; }"
document.head.appendChild(style)

The Modern & Easy Way

The code above is the gist of it; continue reading if you want to know the reasoning.

Why another answer? The accepted answer is old and includes redundant code for outdated browsers like the Internet Explorer. Other answers are unnecessarily complex or use properties like .innerHTML that allow for cross-site scripting attacks.

The type property is not needed

Most of the anwsers set the type property like so: style.type = "text/css". Setting this property is not necessary unless you need to support older browsers.

According to <style>: The Style Information element - HTML | MDN, the type attribute is optional and defaults to text/css:

> type > > This attribute defines the styling language as a MIME type (charset should not be specified). This attribute is optional and defaults to text/css if it is not specified; values other than the empty string or text/css are not used. Note: There is very little reason to include this attribute in modern web documents.

Adding the CSS

To add the CSS, use .textContent as it is safer and faster than alternative methods. Opposite to .innerHTML, it does not parse HTML and can therefore prevent cross-site scripting attacks.

Another similar property, .innerText, is like .textContent but takes CSS styles into account and represents only the "rendered" text content. As we are not interested in "rendered"-only content we prefer .textContent.

What does setting .textContent do?

Setting the .textContent property removes all the node's (element's) children and replaces them with the given string value.

Where to place the element?

The style element should be included in the head: "The <style> element must be included inside the <head> of the document. ...". [<style> ... | MDN]

To get the head use document.head as it has been supported by all major browsers for a long time already so there is no need for other fallbacks.

Solution 7 - Javascript

Oftentimes there's a need to override existing rules, so appending new styles to the HEAD doesn't work in every case.

I came up with this simple function that summarizes all not valid "append to the BODY" approaches and is just more convenient to use and 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][1], [jsfiddle][2] [1]: http://codepen.io/anon/pen/vtHCs [2]: http://jsfiddle.net/8h09zkht/

Solution 8 - Javascript

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

<h1>I'm red!</h1>
<p>I'm blue!</p>

By far the most straightforward solution. All you have to do is type the same as how you'd normally declare style tags, between the backticks

Solution 9 - Javascript

Here is a variant for dynamically adding a class

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

Solution 10 - Javascript

This object variable will append style tag to the head tag with type attribute and one simple transition rule inside that matches every single id/class/element. Feel free to modify content property and inject as many rules as you need. Just make sure that css rules inside content remain in one line (or 'escape' each new line, if You prefer so).

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

Solution 11 - Javascript

You wrote:

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

Why not this?

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

Henceforward you can append CSS rules easily to the HTML code:

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

...or directly to the DOM:

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

I expect this to work everywhere except archaic browsers.

Definitely works in Chrome in year 2019.

Solution 12 - Javascript

All good, but for styleNode.cssText to work in IE6 with node created by javascipt, you need to append the node to the document before you set the cssText;

further info @ http://msdn.microsoft.com/en-us/library/ms533698%28VS.85%29.aspx

Solution 13 - Javascript

This function will inject css whenever you call the function appendStyle like this:
appendStyle('css you want to inject')

This works by injecting a style node into the head of the document. This is a similar technique to what is commonly used to lazy-load JavaScript. It works consistently in most modern browsers.

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>

You can also lazy-load external CSS files by using the following snippet:

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>

Solution 14 - Javascript

as i know there are 4 ways to do that.

var style= document.createElement("style");
(document.head || document.documentElement).appendChild(style);
var rule=':visited {	color: rgb(233, 106, 106) !important;}';

//no 1
style.innerHTML = rule;
//no 2
style.appendChild(document.createTextNode(rule));

//no 3 limited with one group
style.sheet.insertRule(rule);
//no 4 limited too
document.styleSheets[0].insertRule('strong { color: red; }');

//addon
style.sheet.cssRules //list all style
stylesheet.deleteRule(0)  //delete first rule

Solution 15 - Javascript

If the problem you're facing is injecting a string of CSS into a page it is easier to do this with the <link> element than the <style> element.

The following adds p { color: green; } rule to the page.

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

You can create this in JavaScript simply by URL encoding your string of CSS and adding it the HREF attribute. Much simpler than all the quirks of <style> elements or directly accessing 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));

This will work in IE 5.5 upwards

Solution 16 - Javascript

Anyone who is looking for Typescript version,

const addStyles = (styles) => {
  let styleNode : HTMLStyleElement = document.createElement('style'); 
  styleNode.type = 'text/css'; 
  if (styleNode.style)  
    styleNode.style.cssText = styles; 
  else  
    styleNode.appendChild(document.createTextNode(styles)); 
        
  /* Append style to the head element */ 
  document.head.appendChild(styleNode);  
}

Also, in react/vue/angular if direct injection of CSS is needed, you can use posstcss-js to convert CSS into JSS and use CSS-in-JSS to inject a new styleSheet directly. For more info, please follow this documentation.

Update

You can use document.head as well as per @Brandon McConnell's comment.

Solution 17 - Javascript

The most trival answer:

function addStyle (styleText) {
  const styleNode = document.createElement('style'); 
  styleNode.type = 'text/css'; 
  styleNode.textContent = styleText;
  document.documentElement.appendChild(styleNode);  
  return styleNode;
}

Solution 18 - Javascript

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArendView Question on Stackoverflow
Solution 1 - JavascriptChristophView Answer on Stackoverflow
Solution 2 - JavascriptvsyncView Answer on Stackoverflow
Solution 3 - JavascriptTomView Answer on Stackoverflow
Solution 4 - JavascriptChristophView Answer on Stackoverflow
Solution 5 - JavascriptbelazView Answer on Stackoverflow
Solution 6 - JavascripttouchmarineView Answer on Stackoverflow
Solution 7 - JavascriptGarlaroView Answer on Stackoverflow
Solution 8 - JavascriptKabirr singh sahniView Answer on Stackoverflow
Solution 9 - JavascriptMichaelView Answer on Stackoverflow
Solution 10 - JavascriptSpookyView Answer on Stackoverflow
Solution 11 - Javascript7vujy0f0hyView Answer on Stackoverflow
Solution 12 - JavascriptTonyView Answer on Stackoverflow
Solution 13 - JavascriptJoel EllisView Answer on Stackoverflow
Solution 14 - Javascriptdefend orcaView Answer on Stackoverflow
Solution 15 - JavascriptmoefinleyView Answer on Stackoverflow
Solution 16 - JavascriptShujathView Answer on Stackoverflow
Solution 17 - JavascriptChester FungView Answer on Stackoverflow
Solution 18 - JavascriptVinod PoormaView Answer on Stackoverflow