Custom Web Design by Rainbo Design


How To Change CSS Stylesheets With JavaScript

A popular business buzzword in the 1980's was "synergy" - that is, when a combination of objects produces a result that is greater than the sum of the parts. Back then, they were talking about when companies merged to become more productive and profitable. And website designers can create their own synergy by combining the style control provided by CSS stylesheets with the dynamic, interactive properties of JavaScript. There are many times when you can make a more effective design by altering the presentation as the user interacts with your web page by using JavaScript to modify your stylesheet. This tutorial will show you some simple ways that you can use JavaScript and CSS to enhance your web page designs, with examples that will let you find and change CSS rules and stylesheets.

[Modify CSS Rule] •  [Find a CSS Rule] •  [Add a CSS Rule] •  [Remove a CSS Rule] •  [Add or Remove a Stylesheet]


Modifying Individual Element CSS Settings With JavaScript

In designing interactive webpages, it's common to use JavaScript to modify the style settings on individual elements based on the user's actions. One of the most popular uses of JavaScript and CSS in this regard is to allow the user to click on a link to reveal some additional information in a <DIV> whose original CSS is set to "display:none;" or "display:hidden". The usual method is to present a link such as More Info to reveal some special content. Try it yourself by clicking on the link.

The actual JavaScript code is as follows:

  function toggleDisplay(id) {
    theElement = document.getElementById(id);
     if (theElement.style.display == 'none') {
       theElement.style.display = 'block';
      } else {
       theElement.style.display = 'none';
     } // endif display
    return false;
   } // end toggleDisplay()

The JavaScript couldn't be simpler. It reads the current style setting for the ID'd element, and if it's set to "none", it changes it to "block", and vice-versa, so that it toggles the setting every time it's called. You can find similar scripts in thousands of website tutorials, but what many of them neglect to mention is that JavaScript can only read the style settings of an element if they have been explicitly defined using the "style" attribute in the HTML tag itself (ie. "inline"), or if JavaScript has been used previously to set the style. Any CSS style settings in your stylesheets or in the <style> tag are not available to JavaScript through the style property. To get that information, your JavaScript must parse all of the stylesheets attached to your document. You'll see how to change stylesheets in the next section.

The point here is that you can control the CSS style setting on any individual element in your document with JavaScript. You fetch the element's style object, and you can then use the property name to change the setting.


Parsing A Stylesheet in JavaScript

Being able to modify the CSS setting of individual elements is simple enough, but sometimes it would be handy to be able to modify the stylesheet(s) of a document in order to modify the settings by class name or element ID. The stylesheets property of the document object holds an array of all of the stylesheets attached to it. So, for example, to obtain the first stylesheet, you could use:

var mySheet = document.stylesheets[0];

and use it as the starting point, or loop through all of the stylesheets as necessary. But to begin, we'll just work with the first one.

In JavaScript, each stylesheet has an array of rules that contain all of the CSS settings. However, Microsoft Internet Explorer uses a different property name for the rules array than most other browsers and you must account for that in your script, as in:

  if (mySheet.rules) {
    theRules = mySheet.rules; // Internet Explorer
   } else {
    theRules = mySheet.cssRules; // Just about everything else
   }

So now you have an array of the CSS rules in your JavaScript variable "myRules", which you can examine (or "crawl") to find the CSS Rule you want to change. You could use the following JavaScript function to find a particular CSS rule by passing its ID ("#identifier") or class name (".identifier") to the function findCSSRule shown below:

 function findCSSRule(selector) {
  ruleIndex = -1;				// Default to 'not found'
  theRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
   for (i=0; i<theRules.length; i++) {
     if (theRules[i].selectorText == selector) {
      ruleIndex = i;
      break;
     } // endif theRules[i]
   } // end for i
  return ruleIndex;
 } // end findCSSRule()

This function returns an index to the desired rule within the myRules array, or -1 if the rule isn't found. See how the function checks each rule's selectorText property.


Modifying a CSS Rule With JavaScript

Of course, just being able to find CSS rules is no help by itself. We want to be able to change them! Each rule object has a style property for each setting within the rule. So, you can change any part of a rule. Let's say we want to change the font size for the ".codeText" class. We could use a function like:

 function changeRule(selector, property, setting) {
  theRule = mySheet.cssRules ? mySheet.cssRules[findCSSRule(selector)] : mySheet.rules[findCSSRule(selector)];
  eval('theRule.style.' + property + '="' + setting + '"');
  return false;
 } // end changeRule()

This example of how the changeRule function works changes the font color for the class ".codeText" to red. Try it!. The function changeRule is a bit of a cheat since you can't directly manipulate the cssRule content with JavaScript. You need to specify a CSS property in your code, but in order to make the function more flexible, I used the function "eval()" which allows us to construct a JavaScript instruction using variables and have it processed as if it were written in the original script. Note that the changeRule() function requires that you use the JavaScript version of the property name, and not the CSS version. For example, to change the size of the font, you need to use JavaScript's "fontSize" property name, instead of the CSS property name "font-size". You should also note that my changeRule function depends on a global variable mySheet that refers to the first stylesheet attached to the document. Best practice would be to modify the findCSSRule funtion shown here to account for mutiple stylesheets so that it would return both an index to the rule you were looking for, as well as an index to the stylesheet that contains the rule.

Just for fun, I also created a function called toggleColor that swaps the font color on the same class.

  function toggleColor(theClass, color1, color2) {
    ruleIndex = findCSSRule(theClass);
    theRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
    theCSS = theRules[ruleIndex].style.cssText.split(';');   // Parse the rule into components
      for (i=0; i<theCSS.length; i++) {
     if (theCSS[i].indexOf(':') != -1) {		     // Skip any empty entry caused by split()
	pairs = theCSS[i].split(':');			     // Split entry into property/value
        property = pairs[0].toLowerCase();		     // Make property lower case
	property = property.replace(/^\s/, '');		     // Trim leading 
	value = pairs[1].toLowerCase();			     // Make value lower case
	value = value.replace(/^\s/, '');		     // Trim leading 
        if (property == 'color') {
	newColor = (value == color1) ? color2 : color1;	     // Determine the new color based on the current setting
	changeRule(theClass, 'color', newColor);	     // Change the rule
        } // endif property == 'color'
       } // endif theCSS[i].indexOf(':')
      } // end for i
    return false;
   } // end toggleColor()

This function demonstrates a few issues you can run into when you try to parse a CSS rule in JavaScript using the different browser families. To start, I found one reference that said Internet Explorer did not support the cssText property of a rule object, but it works for me in IE version 8, and I expect it to work in most versions going forward. Internet Explorer also converted the property names to upper case, which explains why I call toLowerCase here. Both Internet Explorer and Firefox had a tendency to add a leading space character to the value, even when there was no space in the original stylesheet. I also had to trim the leading space occasionally due to the use of the split() function to separate the property/value pairs in the CSS rule. Like my changeRule example, toggleColor assumes that there is only one stylesheet.


Add A Rule To A StyleSheet With JavaScript

Many JavaScripts work by adding generated content to web pages. That process can be cumbersome when the effect you want relies heavily on CSS to improve the appearance of the design and layout. While small effects are easy to achieve by simply including a style attribute to the various HTML tags, it's often simpler and easier to attach a CSS class or an ID attribute to elements and rely on the browser to apply the effect to them. But then you need to be able to add an external stylesheet to the HTML document itself, which slows down the page loading or may simply not be a practical choice, or modify the stylesheet itself using JavaScript. The funtion below allows you to add a new CSS rule to the document's stylesheet:

 function addCSSRule(selector, newRule) {
  if (mySheet.addRule) {
   mySheet.addRule(selector, newRule);		// For Internet Explorer
   } else {
   ruleIndex = mySheet.cssRules.length;
   mySheet.insertRule(selector + '{' + newRule + ';}', ruleIndex);	// For Firefox, Chrome, etc.
  } // endif mySheet.addRule
 } // end addCSSRule()

You can use either a class selector (ie. ".theClass") or an ID selector (ie. "#theID") when you call the addCSSRule function, along with the content of the rule, (ie. "font-size:12px").


Remove A Rule From A StyleSheet With JavaScript

Although you'll probably rarely need it, JavaScript also allows you to remove a CSS rule from a stylesheet, too:

 function removeCSSRule(ruleIndex) {
  if (mySheet.removeRule) {
   mySheet.removeRule(ruleIndex);		// For Internet Explorer
   } else {
   mySheet.deleteRule(ruleIndex);		// For Firefox, Chrome, etc.
  } // endif mySheet.removeRule
 } // end removeCSSRule()

The removeCSSRule function requires the rule index returned by the function findCSSRule shown above.

Being able to modify the stylesheet of a document gives you much more flexibility in designing your JavaScript-enhanced web pages. Once you've mastered the functions required, it lets you create scripts that run faster and work more smoothly. Keep in mind that the functions shown here rely on obtaining the main stylesheet object in the variable "mySheet". I did this for simplicity and to adhere to a common naming convention that you'll find elsewhere on the web. Best practice will often require that your script examine all of the stylesheets available from the document.styleSheets object, and loop through them one by one.

JavascriptKit.com has the details on Stylesheet Properties in JavaScript, and www.hunlock.com has a great JavaScript Stylesheets tutorial, with charts that detail which functions are available for the various browser families.

A practical application of adding a CSS rule with JavaScript would be to account for differences in CSS support among the major browsers. A web design feature that commonly requires using a graphics program is adding a gradient background. While all of the major browsers support gradients in CSS, they all do it with incompatible property names and syntax. Generally speaking, you should avoid browser sniffing to add custom effects, but there are times when the end justifies the means. So here we go. Click here to add the gradient background to the example <div> below.


This is a <div> to demonstrate adding a gradient background with JavaScript.



The JavaScript function to add the gradient rule is as follows:

 function addGradient(el, startColor, endColor) {
  switch(engine) {
   case('Gecko'):
    addCSSRule(el, 'background: -moz-linear-gradient(top,' +  startColor + ',' + endColor + ');');
   break;
   case('Webkit'):
    addCSSRule(el, 'background: -webkit-gradient(linear, left top, left bottom, from(' + startColor + '), to(' + endColor + '));');
   break;
   case('Opera'):
    addCSSRule(el, 'background: -o-linear-gradient(top,' +  startColor + ',' + endColor + ');');
   break;
   case('MSIE'):
    addCSSRule(el, 'filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=\'' + startColor + '\', endColorstr=\'' + endColor + '\');');
   break;
   case(''):
    addCSSRule(el, 'background:' + startColor);  // default to single color if unrecognized browser
   break;
  } // end switch(engine)
 } // end addGradient

This example is a bad choice in some aspects. It relies on non-standard CSS properties that differ among all of the different browser families. The gradient filter often makes the text a bit ugly in Internet Explorer. And I had to revise my original code in order to support the Webkit-based browsers Chrome and Safari because JavaScript cannot access the stylesheets fully until after the document has loaded. So I had to add an onLoad() function to the <body> tag to initialize the variable 'mySheet'. But I wanted to experiment with CSS gradients, and this particular function does clearly demonstrate that there are often times when you simply must accomodate the differences in the JavaScript and graphics engines in popular browsers. The function is also far less than perfect because it fails to check the version of the browser to see if the W3C Standard CSS Level 3 version of the gradient property is supported. While I was able to find some great examples of browser detection functions, it would have needlessly complicated the JavaScript for this simple example.



Adding A New Stylesheet With JavaScript

There can be occasions when adding a completely new stylesheet to a document can be useful. For example, my JavaScript Slideshow relies heavily on specific CSS settings, and while I could use JavaScript to add individual CSS rules, it's much easier to just add a complete stylesheet and be done with it. My addStylesheet function is shown below:

  function addStylesheet(theHref) {
   if(document.createStyleSheet) {
    document.createStyleSheet(theHref);
     } else {
    var newSheet=document.createElement('link');
    newSheet.setAttribute('rel','stylesheet');
    newSheet.setAttribute('type','text/css');
    newSheet.setAttribute('href',theHref);
    document.getElementsByTagName('head')[0].appendChild(newSheet);
    }
  } // end addStylesheet()

For this function, Internet Explorer includes a handy function 'createStyleSheet'. But, for other browsers we rely on adding a link element using DOM functions. Note that it is important to use complete URLs for the value of 'theHref' because the browser will always automatically convert relative URLs into complete URLs for constructing the value of the 'href' attribute of the styleSheet object. This becomes critical when/if you need to remove (or, more precisely, 'disable') a selected stylesheet.

To demonstrate, Click Here to add a new stylesheet that will change the appearance of this text.

Similarly, Click Here to remove that same stylesheet that will change the appearance of the text above.

The JavaScript for removeStylesheet function is as follows:

  function removeStylesheet(theHref) {
    var sheets = document.styleSheets;
    for (i=0; i

I chose to use the 'disabled' property here because my addStylesheet function supports the MSIE function 'createStyleSheet'. If I just relied on DOM functions, I could use 'document.getElementsByTagName('head')[0].removeChild()'.


This page was last modified on April 14, 2012

Return to Main CSS Tutorial Page





Copyright © 2005-2012 by Richard L. Trethewey - Rainbo Design Minneapolis. It's not that I think this is such an earth-shatteringly great presentation, but if you want to copy it, I'd appreciate it if you would ask for permission.


  Share This Page!