Dynamic SCRIPT and STYLE elements in IE
So you know how to add external scripts and styles, using the DOM, after the page is loaded. And what if you don't have external files, but have some style definitions and some JS code as text and you want it inserted and executed into a page.
The DOM way
"Ha! An easy one", you'd say and then go like:
var ss = document.createElement('script'); var scr = 'alert("bah");'; var tt = document.createTextNode(scr); ss.appendChild(tt); var hh = document.getElementsByTagName('head')[0]; hh.appendChild(ss);
"Ha!" in turn says IE, "No way!"
The IE way for SCRIPT
The above won't work in IE, but you can use the text property instead of creating a text node. Interestingly enough, this also works in Firefox.
var ss = document.createElement('script'); var scr = 'alert("bah");'; ss.text = scr; var hh = document.getElementsByTagName('head')[0]; hh.appendChild(ss);
The IE way for STYLE
STYLE, SCRIPT, what's the difference, they are merely elements of the DOM tree. For the normal browsers, yes, so creating a text node with the stylesheet body will work in Firefox. For IE, you need a workaround.
var ss1 = document.createElement('style'); var def = 'body {color: red;}'; ss1.setAttribute("type", "text/css"); ss1.styleSheet.cssText = def; var hh1 = document.getElementsByTagName('head')[0]; hh1.appendChild(ss1);
Note that while in the SCRIPT case I took the liberty of skipping the type attribute, it's absolutely required here.
So with a bit of object sniffing, we can get a cross-browser solution:
var ss1 = document.createElement('style'); var def = 'body {color: red;}'; ss1.setAttribute("type", "text/css"); if (ss1.styleSheet) { // IE ss1.styleSheet.cssText = def; } else { // the world var tt1 = document.createTextNode(def); ss1.appendChild(tt1); } var hh1 = document.getElementsByTagName('head')[0]; hh1.appendChild(ss1);

January 28th, 2007 at 8:16 pm
[...] Dynamic SCRIPT and STYLE elements in IE - Going conditional on the text attribute For IE you can use the text property instead of creating a text node. Creating a text node with the stylesheet body will work in Firefox. For IE, the type attribute, it’s absolutely required here. So with a bit of object sniffing, we get a x-browser solut (tags: DOM JavaScript) [...]
April 28th, 2007 at 12:17 am
Thank you so much!!
I’ve tried to solve this problem for so long, trying to find the way to dynamically add script and style tags during the ajax-application work.
Now it works in IE too.
August 4th, 2007 at 6:15 am
hey ash,
For me IE is having some problem. how did you solve your problem. please share your idea with me
Thanks
August 24th, 2007 at 2:33 am
Unbelievable, this helped me so much
Thank you guys!!!!!!!!
September 27th, 2007 at 3:51 am
I have a calendar field. which is having one text field and one calendar icon. with this i have a attached with the image. Text field id and icon id is attached in the script variables.
So if you click the image, DHTML caledar box will be opened.
Now let me come to the real problem. i have plus icon. if i click the plus icon i need to add one more set of calendar.
I am adding this new calendar through javascript. In Firefox this is working. but in IE this is not working. new calendar is coming but if i click the icon, DHTML calendar popup is not loaded.
can any one solve my problem.
October 2nd, 2007 at 1:42 am
[...] I looked up a few ways to include a <style> element, but realized there’s an easier way; I split the style into its own stylesheet and added a line to Javascript: $(’head’).append(’<link type=”text/css” href=”/css/kb.css” rel=”stylesheet” >’); before the $(’<div id=”keyboard-holder”>’).insertAfter(’#q’).load(’/inc/keyboard.html’); // load via Ajax and now the style loads dynamically and easily. Luckily, jQuery handles identifying and executing <script> elements in Ajax’ed code, so I don’t have to pull that out. [...]
January 21st, 2008 at 2:04 pm
Thanks a whole lot, this help me immensely. I dynamically insert a javascript function into web page using greasemonkey and have spent three days trying to port it to IE and Reify’s Turnabout until I found this. Thanks again.
March 26th, 2008 at 8:52 am
Your IE Style trick really helped me out, I was getting desperate after trying every other standard/non-standard way! Just a quick note, script.text is actually standard http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#ID-81598695 and works in Safari & Opera as well. It is nice not to have to fork the code on IE for scripts at least…
June 12th, 2008 at 2:31 pm
Great tip, thanks! I was hitting a wall here trying to get this to work on IE. Very cool!
August 14th, 2008 at 1:44 pm
to include other browsers (firefox):
var ss1 = document.createElement(’style’);
var def= ‘#Browse .productLabel{display:none;}’;
ss1.setAttribute(”type”,”text/css”);
if(ss1.styleSheet){
ss1.styleSheet.cssText = def;
var hh1 = document.getElementsByTagName(’head’)[0];
hh1.appendChild(ss1);
}
else
{
ss1.innerHTML = def;
document.getElementsByTagName(’head’)[0].appendChild(ss1);
}
September 26th, 2008 at 1:28 am
Thanks for the tip.
Silly IE 6 & 7 crash each time an import directive is part of the cssText. IE makes me code angry. :/
Extra credit goes to the person who can work around IE crashing at the following statement (without turning it into a LINK element)
ss1.styleSheet.cssText = ‘@import url(”external.css”);’;
Anyone.
September 26th, 2008 at 1:24 pm
ss1.styleSheet.addImport(”external.css”);
Just make sure to do this after manipulating cssText. Manipulating cssText after addImport causes the import to be overwritten.
September 26th, 2008 at 1:26 pm
Good find, thanks for sharing, Matt!
S
October 20th, 2008 at 2:47 pm
Thanks for taking the time to blog this
December 6th, 2008 at 2:22 am
Awesome post. I’ve spent days adn thenh days more trying to get IE to parse and apply am on the fly dhtml css script. I’ve hacked and searched to 2 years (not continually,mind you), but the “styleSheet.cssText” was the missing piece I couldn’t find. Thanks, again, this completely rocks.
As a way of saying thanks, here is an cross domain AJAX call , and can be asynchronous or synchronous:
function _ImportScript(jsurl, bUseCache, CallBackFunc, SafariTest )
{
//Supply CallBack to verify load before accessing loaded objects.
//Use SafariTest to trigger the callback func for safari, e.g. test for vars defined in the loaded script
var head = document.getElementsByTagName(’head’).item(0);
var s = document.createElement(”SCRIPT”);
s.src = ((bUseCache)?jsurl:GetUniqueURL(jsurl));
s.type = “text/javascript”;
if(typeof CallBackFunc == “function”){
if(typeof s.onreadystatechange != “undefined”){//ie
s.onreadystatechange = function(){if(/loaded|complete/.test(s.readyState)){s.onreadystatechange = null; CallBackFunc();} };
}else if(/safari/i.test(navigator.userAgent) && SafariTest ){ //Safari does not support event callbacks
window.SafariLoaded = function(){if(eval(SafariTest)){ CallBackFunc(); }else{ window.setTimeout(”window.SafariLoaded()”,100)}; }
window.SafariLoaded();
}else{
CallBackFunc.once = true;//avoid repeated callbacks
addEvent( s, “load”, function(){ if(CallBackFunc.once){CallBackFunc.once = false; CallBackFunc();} } ); //mac:camino,moz,fx. win:moz,fx,opera 9x
addEvent(window, “load”, function(){ if(CallBackFunc.once){CallBackFunc.once = false; CallBackFunc();} } ); //opera 8x
}
}
head.appendChild(s);
}
January 12th, 2009 at 3:01 pm
I made a variation that will take information added to a DIV via ajax, and then turn it into usable functions
function setAndExecute(divId) {
var div = document.getElementById(divId);
var x = div.getElementsByTagName(”script”);
var ss = document.createElement(’script’);
for( var i=0; i < x.length; i++) {
//alert(x[i].text);
ss.text = x[i].text;
hh = document.getElementsByTagName(’head’)[0];
hh.appendChild(ss)
}
}
January 22nd, 2009 at 5:42 am
Here’s what worked for me (for both IE and Firefox):
var lnk = document.createElement(’link’);
lnk.rel=’stylesheet’;
lnk.type=’text/css’;
lnk.href=’name_of_css_file’);
document.getElementsByTagName(’head’)[0].appendChild(lnk);
January 26th, 2009 at 11:57 am
Yep, Sigalit Ur, your way (DOM inclusion) works when you have an external stylesheet.
The problem I was solving in the post was a little different - when you don’t have an external stylesheet, but you have a bunch of style definitions and you want to inline them.
Best,
Stoyan
February 5th, 2009 at 4:52 am
On IE it seams to be a problem with pseudo-class. They are not applied. Can anyone give me a solution?
Here is an example:
function addStyles(styles) {
var head = document.getElementsByTagName(’head’)[0];
var style = document.createElement(’style’);
style.type = ‘text/css’;
if (style.styleSheet) { // IE
style.styleSheet.cssText = styles;
} else { // others
var tt1 = document.createTextNode(styles);
style.appendChild(tt1);
}
head.appendChild(style);
}
addStyles(’.una tr:first-child > td { border-top: none; } .una { border-bottom: 1px solid #BEBEBE; } .una td { border-top: 1px solid #BEBEBE; border-bottom: 1px solid Red; }’);
12
12
12
The css rule ‘.una tr:first-child > td’ is not applied.
Thx
February 5th, 2009 at 4:55 am
This is the html code:
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”>
<html>
<head>
</head>
<body>
<script>
function addStyles(styles) {
var head = document.getElementsByTagName(’head’)[0];
var style = document.createElement(’style’);
style.type = ‘text/css’;
if (style.styleSheet) { // IE
style.styleSheet.cssText = styles;
} else { // others
var tt1 = document.createTextNode(styles);
style.appendChild(tt1);
}
head.appendChild(style);
}
addStyles(’.una tr:first-child > td { border-top: none; } .una { border-bottom: 1px solid #BEBEBE; } .una td { border-top: 1px solid #BEBEBE; border-bottom: 1px solid Red; }’);
</script>
<table border=0 width=100% class=”una” cellspacing=”0″ cellpadding=”0″>
<tr><td>1<td><td>2<td></tr>
<tr><td>1<td><td>2<td></tr>
<tr><td>1<td><td>2<td></tr>
<table>
</body>
</html>
February 5th, 2009 at 6:15 am
I found a solutin to readd the rules:
if (style.styleSheet) { // IE
var css = document.styleSheets['calculeStyles'];
for(var i = css.rules.length; i > 0; i–)
{
changeCssRule(css, css.rules[0].selectorText, css.rules[0].style.cssText);
css.removeRule(0);
}
}
but …
February 5th, 2009 at 2:02 pm
Thankssssssssssssssssss GOD!!!!!!
I was struck in this problem since last week and this SUCKY DAMN IE was not letting me create text node inside of script tab. I really appreciate your help. God Bless you.
A’meen
March 24th, 2009 at 3:59 pm
Marian,
Try moving the head.appendchild up, it worked for me in ie7:
function addStyles(styles) {
var head = document.getElementsByTagName(’head’)[0];
var style = document.createElement(’style’);
style.type = ‘text/css’;
head.appendChild(style);
}
if (style.styleSheet) { // IE
style.styleSheet.cssText = styles;
} else { // others
var tt1 = document.createTextNode(styles);
style.appendChild(tt1);
}
April 6th, 2009 at 9:57 pm
great post, thanks for your help
May 16th, 2009 at 4:01 pm
Is this method is cross-browser? What about Safari?
June 12th, 2009 at 12:48 am
Thanks for this.
Following simple function can be used for cross browser support:
function agent(v) { return(Math.max(navigator.userAgent.toLowerCase().indexOf(v),0)); }
if (agent(’msie’)) { // IE
I hate IE 6
} else {
rest of the world
}
July 3rd, 2009 at 4:28 am
[...] The problem I found is when you set styles dynamically. Say you have a bunch of CSS content as a string and you want to create a new style tag and shove the code there. I’ve blogged about this before. [...]