How To Dynamically Swap External Style Sheets

Go here to see a demo, or first read through the annotated code:
The demo consists of seven small files: Only two of these files contain code and only one file, changecss.js, contains the actual code that enables the swap. The base.css file contains all the non-swappable CSS used by the HTML for the demo, mostly formatting information that is non-color oriented - e.g. setting the sizes of things. The other four CSS files represent themes. It is these files that we can swap to change the theme of the demo page on the fly. We'll look at changecss.js first, then we'll see how the single function in changecss.html calls the methods therein.
The function names are rather long, but I like things to be self-explanatory. Of the two, we need to use the removeExternalStyleSheetLink function first. When first loaded, the demo page is linked to the theme CSS file named mono.css. However, the demo user is allowed to swap in any of the other theme CSS files. In order for this to happen, the demo first calls upon the removeExternalStyleSheetLink function to remove the link to mono.css, i.e.: <link id="mono" rel="stylesheet" type="text/css" href="mono.css" media="screen" />. Notice the rather unusual fact that the link has an id attribute - this is perfectly legal HTML (it's just not done very often). This id value of "mono" is the value that must be passed in the cssLinkId argument to the function. The function uses it to get a reference to the DOM object of the external style sheet link that must be removed, and then does the removal by telling the parent of this DOM object to "remove me".
Once the link to the original CSS theme file is gone, it is time to call the second function, createExternalStyleSheetLink. The job of this function is to create a DOM object that will represent a link to the CSS file that is to be "swapped in". Like the removal function, the create function takes an id as an argument, because it is important to give this new link tag an id. Giving it an id attribute makes it easy to reference it in case it too will be swapped out at some future time. The second argument, href, will of course contain the name of the CSS file that will be linked to (i.e. swapped in). The function uses the standard DOM manipulation JavaScript functions "createElement" and "appendChild" to perform the work of creating the link object in memory and then inserting it into the proper place in the DOM. The proper place is in the head of the document, as denoted by the invocation: document.getElementsByTagName("head")[0].
///// changecss.js /////

function removeExternalStyleSheetLink(cssLinkId) {
  var cssLink = document.getElementById(cssLinkId);
  cssLink.parentNode.removeChild(cssLink);
}

function createExternalStyleSheetLink(cssLinkId, href) {
  var cssLink = document.createElement("link");
  cssLink.id = cssLinkId;
  cssLink.type = "text/css";
  cssLink.rel = "stylesheet";
  cssLink.href = href;
  cssLink.media = "screen";
  document.getElementsByTagName("head")[0].appendChild(cssLink);
}
      
Now we'll take a quick look at changecss.html. I'll show the entire file but the the main point of interest is the solo function named changeStyleSheet. Most of the rest of what is there merely exists to provide objects whose colors can be changed by a theme switch (i.e. proof of concept). Note that I don't necessarily advocate defining functions in HTML pages, but in this case, the function is quick and dirty and relies upon embedded page knowledge. I'm doing a couple other naughty things here, for instance, using a non-namespaced global variable. Please bear in mind that I am striving for brevity and clarity of presentation - not necessarily trying to use best practices. Before we look at the changeStyleSheet function, note again the link tag containing the id of "mono". That is the default theme that may be swapped out by pressing either the "Apply Red Theme", "Apply Green Theme" or "Apply Blue Theme" buttons. It is worth noting that the act of swapping the CSS files causes the page to radically change it's appearance, but this does not cause a page refresh.
There isn't really much to look at in the changeStyleSheet function. We already understand how the removeExternalStyleSheetLink and removeExternalStyleSheetLink functions work, and the changeStyleSheet function does little more than simply call them in succession. The remainder of what the function does revolves around remembering the name of the CSS file for the current theme and displaying that information to the user.
<!-- changecss.html -->

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="pragma" content="no-cache">
<link rel="stylesheet" type="text/css" href="base.css" media="screen" />
<link id="mono" rel="stylesheet" type="text/css" href="mono.css" media="screen" />
<script type="text/javascript" src="changecss.js"></script>
<script type="text/javascript">
  var gCurThemeName = "mono";

  function changeStyleSheet(newThemeName) {
    removeExternalStyleSheetLink(gCurThemeName);
    createExternalStyleSheetLink(newThemeName, newThemeName + ".css");
    gCurThemeName = newThemeName;
    document.getElementById("using").innerHTML = gCurThemeName + ".css";
  }
</script>
</head>
<body>
  <div id="titlebar">Dynamically Change CSS</div>
  <p>
  currently using:
  <span id="using">mono.css</span>
  </p>
  <div id="spacer">
    <span id="buttons">
      <input type="button" value="Apply Red Theme" onclick="changeStyleSheet('red')" />
      <input type="button" value="Apply Green Theme" onclick="changeStyleSheet('green')" />
      <input type="button" value="Apply Blue Theme" onclick="changeStyleSheet('blue')" />
    </span>
  </div>
</body>
</html>
      
Here is base.css. This CSS file never gets swapped out - which is of course the normal scenario for CSS files.
/* base.css */

body {
  margin: 0;
  padding: 0;
  background-color: lightgray;
  text-align: center;
}

#titlebar {
  padding: 20px;
  font-size: 40px;
  color: white;
}

#using {
  margin-left: 5px;
  padding: 0 5px 2px 5px;
  background-color: white;
  font-weight: bold;
}

#spacer {
  margin-top: 80px;
}

#buttons {
  border-style: solid;
  border-width: 2px;
  padding: 10px;
  background-color: white;
}
      
To complete the article I show here the listings of all four of the CSS files that make up the themes. There is nothing special at all about the makeup or structure of these files - they are just standard CSS files.
/* mono.css */

body {
  background-color: lightgray;
}

#titlebar {
  background-color: black;
}

#using {
  color: black;
}

#buttons {
  border-color: black;
}
      
/* red.css */

body {
  background-color: #FF7373;
}

#titlebar {
  background-color: #A00600;
}

#using {
  color: #A00600;
}

#buttons {
  border-color: #A00600;
}
      
/* green.css */

body {
  background-color: #73FF73;
}

#titlebar {
  background-color: #00A600;
}

#using {
  color: #00A600;
}

#buttons {
  border-color: #00A600;
}
      
/* blue.css */

body {
  background-color: #7373FF;
}

#titlebar {
  background-color: #0000A6;
}

#using {
  color: #0000A6;
}

#buttons {
  border-color: #0000A6;
}
      

You can see this code in action here.

An expanded version of this article is available on the Uberiquity Blog, here.