del.icio.us .:. stumble .:. digg

Creating Dynamic Stylesheets .:. kentbrewster.com

Recently I found myself in the position of needing to code a series of syndicated Web badges. To guarantee that they ran as consistently as possible, I started looking for ways to create stylesheets with JavaScript, instead of having to do an additional HTTP request, and--assuming the stylesheet actually loaded--worry about the possibility that my selectors could be overridden by an additional set of rules loaded somewhere else on the page.

To the right should be an example. If you don't see a yellow square with a red outline and the word "woot!" inside, it's not working on your browser. As of right now I see it in IE6, Safari 2, Mozilla 2, and Opera 9 ... if you're using a browser lower than my tested versions and it's working, or it's not and you think it should, please leave a comment with your setup information and what you're seeing.

Documentation in this area is pretty thin on the ground, so here's what worked for me:

// make a new stylesheet
var ns = document.createElement('style');
document.getElementsByTagName('head')[0].appendChild(ns);

// Safari does not see the new stylesheet unless you append something.
// However!  IE will blow chunks, so ... filter it thusly:
if (!window.createPopup) {
   ns.appendChild(document.createTextNode(''));
}
var s = document.styleSheets[document.styleSheets.length - 1];

// some rules to apply
var rules = {
   ".woot" : "{ float: right; margin:10px; background-color:#ff0; border:5px solid #f00; text-align:center; width:100px; }",
   ".woot p" : "{ line-height:100px; margin:auto; color:#00f; font-weight:bold;}"
}

// loop through and insert
for (selector in rules) {
   if (s.insertRule) {
      // it's an IE browser
      try { 
         s.insertRule(selector + rules[selector], s.cssRules.length); 
      } catch(e) {}
   } else {
      // it's a W3C browser
      try { 
         s.addRule(selector, rules[selector]); 
      } catch(e) {}
   }               
}

// find the div you want to futz with
var div = document.getElementById('woot');

// give it the class name
div.className = 'woot';

// build some structure inside
var p = document.createElement('P');
p.innerHTML = 'woot!';
div.appendChild(p);

As always, please feel free to try this out yourself, and let me know how it goes.

Post a Comment

Nicholas C. Zakas .:. 20071126091509
I wrote about injecting CSS into a page a little while ago at the YUI Blog: http://yuiblog.com/blog/2007/06/07/style/

Copyright Kent Brewster 1987-2008 .:. FAQ .:. RSS .:. Contact