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 capabilities of JavaScript. There are many times when you can make a more effective web page 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, examine, and modify CSS rules and entire stylesheets.

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) {
    var 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) {
  var ruleIndex = -1;				// Default to 'not found'
  var 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) {
  var 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 it sets the element's 'style' property instead of changing the original rule in the stylesheet. So to use this function, 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.

To demonstrate how to change a rule within a stylesheet, I also created a function called toggleColor that swaps the font color on the selected class rule.

  function toggleColor(theClass, color1, color2) {
    var ruleIndex = findCSSRule(theClass);
    var theRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
    var theCSS = theRules[ruleIndex].style.cssText.split(';');   // Parse the rule into components
    var pairs, property, value, newColor = null;
      for (var 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"). Just remember to include the entire identifier when you call the function.


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 now support the W3C standard for gradients in CSS, older versions 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('MSIE'):
    addCSSRule(el, 'filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=\'' +
      startColor + '\', endColorstr=\'' + endColor + '\');');
    addCSSRule(el, 'background: -ms-linear-gradient(to bottom,' +  startColor + ',' + endColor + ');');
   break;
   default: // Finally, add the W3C Standard rule
    addCSSRule(el, 'background: linear-gradient(to bottom,' +  startColor + ',' + endColor + ');');
  } // end switch(engine)
 } // end addGradient

This example originally relied on vendor prefixes that added different rules for each of the different browser families to support older versions. That's no longer necessary. And the gradient filter often makes foreground text a bit ugly in Internet Explorer. Thankfully, IE 10 supports the W3C standard now. I had to revise my original code in order to support the Webkit-based browsers Chrome and Safari because in those browsers, JavaScript cannot access the stylesheets fully until after the document has loaded. So I had to add an onLoad() event listener function to initialize the variable 'mySheet' properly in all browsers. 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.



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<sheets.length; i++) {
     if (sheets[i].href == theHref) {
       sheets[i].disabled = true;
     } // endif sheets[i].href
    } // end for i
  } // end removeStylesheet()

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 something like: 'document.getElementsByTagName('head')[0].removeChild()'.



More CSS Tutorials

CSS Positioning
CSS Nested DIVs & Floats Tutorial
CSS Effects on Element Size
CSS Visibility Tutorial
CSS Centering Tutorial
CSS Vertical Align Tutorial
CSS Overflow Tutorial
Changing Stylesheets With JavaScript
When To Use Class or ID in CSS
Multiple Backgrounds in CSS3
How CSS Affects Element Size
Styling tables with CSS

Help Me Make This Page Better

A major limitation of the JavaScript presented here is that it is designed to work with a single stylesheet. Best practice would be to locate all of the stylesheets associated with your document - both embedded and external - and have the code crawl through each one as it processes the various functions. Like many of my tutorials, this one started out with a simple demonstration. And when it looked like using JavaScript to modify stylesheets was a popular topic, I expanded it with more and more functions, but I was locked in to my original one-sheet approach. Over the past year or so, I've worked on adding multiple stylesheet capabilities, but I would run into problems and just haven't set aside enough time to finish yet. But if you have any questions or suggestions for ways to make this page better, please click on the "Talk To Me" link at the bottom of the page. Thanks!


This page was last modified on December 09, 2015


Copyright © 2005-2017 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. I've been working with computers for over 30 years now, and one phrase keeps popping into my head - "I hate it when it's right!" And laptops and smartphones are no better.

Looking for more website design information? See my Sitemap!


  Share This Page!  
Still Have Questions? 
Talk To Me! Click Here!