JavaScript and external stylesheets

This page is marked as In Progress so expect small errors or unfinished bits

You should realise that it is possible to use multiple external stylesheets on a Web page and therefore that you might need to do more than just access a single external stylesheet with JavaScript. Unfortunately there is no obvious way to do that other than looping through the stylesheets and looking for the correct one.

There are also browser issues to contend with (and not just in IE as Chrome and Safari also fail to follow the rules on alternate stylesheets.

Accessing more than one stylesheet using JavaScript

If you know the order of the sheets you could just use the index number to access them:

document.styleSheets[0]
        

The styleSheets object contains all stylesheets LINKed to from the current page. It can be thought of as an array holding the content of all of the stylesheets used on the page. This includes both external stylesheets and embedded stylesheets.

To write good code though you need to allow for someone changing the HTML or CSS by adding stylesheets or changing their order. You need to look through the stylesheets to find the one you want:

for (var i=0; i<document.styleSheets.length; i++) {
  if (document.styleSheets[i].title=="styles2") {    
    alert('Success in finding the stylesheet at position: '+i);
    break;
  }
}
        

The code loops through the stylesheets looking for the one with the title "styles2" and then stops. only the first one being used on page load. Create three stylesheets and a Web page following this page. Then try the above code (you can just put it in SCRIPT tags at the end of the BODY or put it in a function with an event trigger).

Accessing the rules within the stylesheet

Once you have identified the correct stylesheet using the above code you can look through the rules to find the one you want. Here i is the variable containing the number of the stylesheet so you need to leave the above loop in for this to work (pu tthis code just after it):

for (var j=0;j<document.styleSheets[i].cssRules.length;j++) {
  if(document.styleSheets[i].cssRules[j].selectorText='body'){
    document.styleSheets[i].cssRules[j].style.color="#00FF00";
    alert('The body selector was found and was in position '+j+' out of '+document.styleSheets[i].cssRules.length+' rules')
  }
}
        

The FOR loop will run through all of the rules in the stylesheet (cssRules.length is the number of rules found). If there is a matching rule there will be an alert and then the loop will be stopped. You should probably also allow for not finding the CSS rule at all.

Displaying the rules within all stylesheets

If you struggled to understand that it might help you to see the stylesheets and CSS rules for a page. For this to work well you really need a page which uses more than one stylesheet (with titles) and each having more than one rule! Use a standards-compatible browser (Opera or Firefox). Paste this script after the </BODY> tag but before the </HTML> tag.

          
for (var i=0; i<document.styleSheets.length; i++) {
  var stylesheetTitle=document.createElement('h1');
  stylesheetTitle.textContent=document.styleSheets[i].title;
  document.body.appendChild(stylesheetTitle);
  for (var j=0;j<document.styleSheets[i].cssRules.length;j++) {
    var styleRule=document.createElement('p');
    styleRule.textContent=document.styleSheets[i].cssRules[j].cssText;
    document.body.appendChild(styleRule);
  }
}
        

By nesting the second FOR loop the styles are listed under the heading of the title of each sheet.

Application

To amend a stylesheet style the easiest way is probably to use in-line styles and override any external styles. If you are trying to do something more sophisticated and need to change the external styles you can adapt the above code to:

  1. find the appropriate stylesheet
  2. find the position of the rule which sets the existing style (which you want changed)
  3. use those two numbers (i and j in the above examples) to set the new value

Selecting alternate stylesheets

It is also possible to change the stylesheet being used rather than changing individual properties although browser incompatibility continues to be a problem. The first step is to set up more than one stylesheet as you did above following the instructions on the page about CSS and multiple stylesheets.

Once you have a page with multiple stylesheets you can use JavaScript to disable the preferred stylesheet and enable one of the alternates. Create a function in the HEAD section of the Web page or in an external JavaScript source file:

function changeStyleSheet() {
	alert('The number of stylesheets on this page is: '+document.styleSheets.length);
	document.styleSheets[1].disabled=false;
	document.styleSheets[0].disabled=true;	
}
  		

At the bottom of the existing page add an event trigger such as:

<button onmouseup="changeStyleSheet()">Press me</button>
  		

Load the page in a browser and results may vary. Browsers which follow standards will only use the first stylesheet when the page first loads (so the page will be black on white). However, they will report all three stylesheets in the ALERT. Then they switch to the second stylesheet and disable the first one (resulting in yellow on blue).

Other browsers which do not follow standards may work partly or not at all. For example, Safari and Chrome do not recognise the presence of the alternate stylesheets unless you remove the TITLE attributes (and if you do that the script will fail in the other browsers). To allow for both you would need to check for compatibility and offer both approaches. That involves spotting which browser is which and using or not using TITLEs though and that is notoriously difficult to keep up-to-date.

You would be able to come up with a JavaScript-based system which allows the user to express a preference (a drop down menu perhaps) and then record that in a cookie. However, a better solution is to use server-side scripting to record stylesheet choice in a cookie and then offer only one stylesheet to the browser to avoid any chance of confusing the poor thing!

submit to reddit Delicious Tweet