In Javascript it often makes sense to attach a stylesheet rather than style a bunch of individual attributes. Appending a stylesheet to the DOM has a number of advantages:
- Stylesheets can be easier to work with than Javascript—it’s just more natural to use CSS syntax for styling.
-
It’s nice to avoid the cross-browser headaches associated with Javascript styling. Compare CSS’s simple
float: left
to Javascript’sstyle.styleFloat = 'left'
andstyle.cssFloat = 'left'
. - Appending a stylesheet is better for performance when styling 15 or more elements.
-
CSS allows you to leverage pseudo-classes and define styles with the simple
a:hover
selector instead of bothonmouseover
andonmouseout
event listeners.
There are a couple ways to append a stylesheet. Although it’s usually best to attach an external stylesheet, there are times when you need to build a stylesheet on the fly with Javascript. Let’s walk through the code we’ll need to append a style tag in all browsers:
1. Build the style node
Let’s start by creating a style node and attaching some attributes:
<script type="text/javascript">
var css = document.createElement('style');
css.type = 'text/css';
</script>
Here we created a style node in the DOM and added type="text/css"
. If you need to attach a media attribute, simply add: css.media = 'screen'
.
2. Attach various CSS styles
There are a variety of ways to append the CSS content to our style node, however we’ll go through a simple one that works in all browsers. First we need to define all of our styles as a string, and then append them to our style node:
<script type="text/javascript">
var css = document.createElement('style');
css.type = 'text/css';
var styles = '#header { color: #555 }';
styles += ' #content { color: #333; text-align: left; }';
if (css.styleSheet) css.styleSheet.cssText = styles;
else css.appendChild(document.createTextNode(styles));
</script>
Appending the CSS content to the style node gets a bit tricky for multiple browsers. css.styleSheet.cssText
defines the style content for IE so we start with a feature-check for css.styleSheet
. Otherwise we create a text node with our styles
and append it to our style node. It is important to append a text node here—innerHTML
works in Firefox, Safari and Opera but fails in Chrome.
3. Append style node to the head
Finally, we need to append our style node to the DOM, but let’s not do it in the HTML <body>
. Besides being invalid, appending a style node to the document body can cause styling issues.
We’ll start with a cross-browser safe method to find the document head, and then append the style node:
<script type="text/javascript">
var css = document.createElement('style');
css.type = 'text/css';
var styles = '#header { color: #555 }';
styles += ' #content { color: #333; text-align: left; }';
if (css.styleSheet) css.styleSheet.cssText = styles;
else css.appendChild(document.createTextNode(styles));
document.getElementsByTagName("head")[0].appendChild(css);
</script>
Here we use document.getElementsByTagName("head")[0]
to focus in on the head element, then append our style node.
4. Make sure to append it after the DOM loads
Last but not least we need to call this at the correct time: if we try to append our style node before the document loads it’ll throw an error. So let’s make sure we’re calling it after the document loads (and wrap it all in a function for easy reuse):
<script type="text/javascript">
function appendStyle(styles) {
var css = document.createElement('style');
css.type = 'text/css';
if (css.styleSheet) css.styleSheet.cssText = styles;
else css.appendChild(document.createTextNode(styles));
document.getElementsByTagName("head")[0].appendChild(css);
}
var styles = '#header { color: #555 }';
styles += ' #content { color: #333; text-align: left; }';
window.onload = function() { appendStyle(styles) };
</script>
Here we used the traditional event handler model (onload
) to define the event, but feel free to use any event handler you like.
And that’s all there is to it! This technique works in all modern browsers.
I didn’t know you had to wait for the document to load before appending a style (or link) element to the head of a document,
Since I didn’t know it, I’ve been inserting them before the body loads for years,
and my pages have always opened with the .css files loaded and all the styles enforced.
I’ll keep an eye on this in the future, in case the browser venders read your article and change their behavior, but otherwise I’m going to try to recover my ignorance and keep on inserting in place…
But you can remove the style element you created? I can’t