11.6 Changing Imported Style Sheets After Loading

NN 6, IE 5(Win)

11.6.1 Problem

You want users to be able to select a different user interface "skin" for the page by loading a different .css file into a page already being viewed in the browser.

11.6.2 Solution

If you truly adhere to the spirit of separating content from rendering, the look and feel of a page can be controlled exclusively by style sheets. Designing different style sheets can transform the overall appearance of the pagebackground and foreground colors, margins, font specifications, and so oneven while the content remains the same. If you use a <link> element to import the default skin, you can assign a URL to a different .css file to import a different skin. Here is a sample <link> element:

<link id="basicStyle" rel="stylesheet" type="text/css" href="styles.normal.css" />

To load a new external style sheet into the link, use the following:


After the new file loads, Internet Explorer 5 and later for Windows and Netscape 6 and later automatically apply the new style definition to the document. IE 5 for the Mac does not apply the new external styles.

11.6.3 Discussion

There are other ways to refer to style sheets as objects (via the document.styleSheets collection, for example), but Netscape through Version 7 does not respond well to modifying the href property of a styleSheet object referenced in this manner. On the other hand, if you must support Internet Explorer 4 (which does not have the getElementById( ) method of the W3C DOM), you can use either the document.styleSheets collection or the proprietary document.all reference of Internet Explorer.

If you allow users to set preferences such as design skins, you should preserve those settings so that they are employed automatically the next time they visit the site. The most efficient way to do this is to save the preference on the client machine in a cookie. For example, your page could include a group of radio buttons, each signifying a skin design choice. Each radio button's value attribute is the URL of the associated skin's .css file. Each button's onclick event handler invokes a function that both loads the new skin choice and preserves the setting in a cookie (with the help of a cookie utility, such as the one in Recipe 1.9):

function setSkin(evt) {
    // equalize IE and W3C event models
    evt = (evt) ? evt : ((window.event) ? window.event : null);
    if (evt) {
        var btn = (evt.srcElement) ? evt.srcElement : evt.target;
        document.getElementById("basicStyle").href = btn.value;
        setCookieValue("skin", escape(btn.value));

Your scripts also then bear the responsibility of assigning the saved skin URL the next time the page loads. But you must also take into account browsers with cookies and/or scripting turned off. To do this, include the hardwired <link> element as before, but follow it with script statements in the head that retrieve cookie data and, if present, assign the preserved value to the href property of the link element:

var skin = getCookieValue("skin");
if (skin) {
    document.getElementById("basicStyle").href = unescape(skin);

To complete the UI design, your page should also set the checked attribute of the radio button corresponding to the saved value. You can either use document.write( ) to generate the radio button HTML or an onload event handler for the page to loop through the radio button set for a match between the saved skin value and the value property of one of the buttons (see Recipe 8.12).

11.6.4 See Also

Recipe 11.8 for scripts that toggle between already loaded style sheets; Recipe 1.9 for reading and writing cookies; Recipe 12.4 for a demonstration of using a cookie to set style preferences.