[javascript] Add CSS to <head> with JavaScript?

Is there a way to add css from a string in the javascript file to the head of a document with javascript?

Let's say we have a webpage, which has a lightbox script, this script requires a css file to function.

Now adding this css file with <link> will make the css file download even for people that don't have js enabled.

I know that I can dynamically load the css file with the script, but that also means that there will be 2 http requests, and in cases where there is little to no css in the file I find this inefficient.

So I thought to myself, what if you could put the css that you have in the css file, into the script, have the script parse the css and add it into the head, or even better just have the script add the css directly into the <head> of the document.

But I have found nothing online that suggests that this is possible, so is it possible to add css to the head with js?

Edit + SOLUTION:

I edited roryf's answer to work cross browser (except 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);
 }

This question is related to javascript html css

The answer is


Here's a simple way.

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

Here's a function that will dynamically create a CSS rule in all major browsers. createCssRule takes a selector (e.g. "p.purpleText"), a rule (e.g. "color: purple;") and optionally a Document (the current document is used by default):

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

If you don't want to rely on a javascript library, you can use document.write() to spit out the required css, wrapped in style tags, straight into the document head:

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

This way you avoid firing an extra HTTP request.

There are other solutions that have been suggested / added / removed, but I don't see any point in overcomplicating something that already works fine cross-browser. Good luck!

http://jsbin.com/oqede3/edit


A simple non-jQuery solution, albeit with a bit of a hack for 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]);

It seems IE does not allow setting innerText, innerHTML or using appendChild on style elements. Here is a bug report which demonstrates this, although I think it identifies the problem incorrectly. The workaround above is from the comments on the bug report and has been tested in IE6 and IE9.

Whether you use this, document.write or a more complex solution will really depend on your situation.


Edit: As Atspulgs comment suggest, you can achieve the same without jQuery using the querySelector:

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

Older answer below.


You could use the jQuery library to select your head element and append HTML to it, in a manner like:

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

You can find a complete tutorial for this problem here


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width