Yay! Programmer art!
Yay! Programmer art!

A cross browser changeCSS function to alter, add, or delete CSS rules

Last year I needed a function to change CSS rules for one of my projects, so I put together a function called changeCSS() which allowed me to change, add or delete a CSS rule. I looked at various resources and the work was heavily influenced by code from David Flanagan and Shawn Olson. It worked great for all the cases I needed it in my project. My plan was to rigorously test it to make sure it worked in other cases I hadn’t used then post it here, but over time it has become clear that isn’t going to happen. So I decided I’d just put it out here as “yet another semi-tested but handy function” that people can look at for reference.

Anywhere, here is the function.


var exfer = window.exfer || {};
exfer.changeCSS = function (selector, stylename, value) {
  var ss, rules;
 
  // make sure there is a stylesheet available
  if (document.styleSheets.length <= 0) {
    if (document.createStyleSheet) {
      document.createStyleSheet();
    } else {
      var styleTag = document.createElement("style");
      styleTag.type = "text/css";
      document.getElementsByTagName("head")[0].appendChild(styleTag);
    }
  }
 
  // convert the stylename to camel case if necessary
  ccstylename = (stylename || "").replace(/\-(\w)/g, function (m, c) { return (c.toUpperCase()); });
  ccstylename = (ccstylename == 'float') ? 'cssFloat' : ccstylename;
  selector = selector.toLowerCase();
 
  // loop to delete or change the css
  for (var i = 0; i < document.styleSheets.length; i++) {
    ss = document.styleSheets[i];
    try {
      rules = ss.cssRules || ss.rules;
    } catch (e) {
      rules = []
    }
    for (var j = 0, len = rules.length; j < len; j++) {
      if (rules[j].selectorText && rules[j].selectorText.toLowerCase() == selector) {
        if (value != null) {
          rules[j].style[ccstylename] = value;
        } else {
          if (ss.deleteRule) {
            ss.deleteRule(j);
          } else if (ss.removeRule) {
            ss.removeRule(j);
          } else {
            // poor man's delete
            rules[j].style.cssText = "";
          }
        }
        return;
      }
    }
  }
 
  if (stylename && value) {
    // if the selector wasn't found and isn't supposed to be deleted then add it
    ss = document.styleSheets[0];
    rules = ss.cssRules || ss.rules;
    if (ss.insertRule) {
      ss.insertRule(selector + "{" + stylename + ":" + value + "; }", rules.length);
    } else if (ss.addRule) {
      ss.addRule(selector, stylename + ":" + value + ";", rules.length);
    } else {
      throw new Error("Selector not found and add/insert rule not supported.");
    }
  }
};

Below is a test div that starts bold and you can change the color. You can even delete the whole rule and remake it.

A test DIV

exfer.changeCSS(”#changediv”, “background-color”, “yellow”);

exfer.changeCSS(”#changediv”, “background-color”, “green”);

exfer.changeCSS(”#changediv”, “background-color”, “”);

exfer.changeCSS(”#changediv”, “background-color”);

Overall I think it is a handy function. I did my minimal testing in IE6/7, FF2, Opera 9, and Safari 3 all in Windows.

5 Comments

  1. Joeri Sebrechts
    Posted January 22, 2009 at 9:58 am | Permalink

    I found out the hard way that addRule doesn’t support multiple selectors separated by “,”, where insertRule does. I ended up splitting the selector on the comma character and adding separate rules for each segment.

  2. Posted January 29, 2009 at 1:34 am | Permalink

    That’s a good point I hadn’t considered. Thanks for pointing it out.

  3. Glen
    Posted August 17, 2009 at 12:11 pm | Permalink

    Looks to me like the closing “}” on the try statement is missing.

  4. Posted September 18, 2009 at 8:01 am | Permalink

    Right you are. Somehow that got stripped out when I pasted it in to WordPress. Should be fixed now. :)

  5. juan
    Posted October 22, 2010 at 8:32 am | Permalink

    not working in Chrome

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*

For spam detection purposes, please copy the number 2257 + 1 to the field below: