Home Articles FAQs XREF Games Software Instant Books BBS About FOLDOC RFCs Feedback Sitemap
irt.Org

Related items

Why use CSS?

An Introduction to Cascading Style Sheets

Dynamic StyleSheets

You are here: irt.org | Articles | Cascading Style Sheets (CSS) | Dynamic StyleSheets [ previous next ]

Published on: Saturday 28th February 1998 By: Michael Bednarek

Introduction

With the advent of Dynamic HTML, we have been able to do a lot more with our scripts. Everything on the page becomes an object to be manipulated. In this article, you will learn how to change a page's style sheet on the fly.

Why would you want to do this? Well, you might be very good at writing content but not so hot when it comes to page design - you could give the user a choice of stylesheets and let him use the one he likes best. Or your site might be part of several Web rings, so you might want a different style depending on where the user was coming from.

For the purpose of this article, we'll use the first example. We'll create a "Customise" page which enables the user to browse through all the styles. He can then select the one he wants by pressing a button. Why is this button necessary, you might ask. Well, most Web sites are made up of more than one page, and so the other pages on the site will also need to know which stylesheet to use. Pressing a button could store the choice in a cookie which can be read by the other pages. This also ensures that the site displays the user's preferred style the next time he visits.

At the moment the only browsers that support Cascading Style Sheets are Microsoft Internet Explorer version 3 (very limited support - does not support document.styleSheets), Microsoft Internet Explorer 4, and Netscape Navigator version 4. Although there are differences in the two version 4 implementations. The major being is that the Document Object Model in Explorer allows control over the documents style sheet through the new object styleSheet. This allows the various styles to be altered without the page being reloaded.

To overcome the lack of this feature in Navigator we will use Layers. We can use Layers in Navigator to show or hide parts of a document. We can also use Layers to show the contents of another document in the current document. It is this second feature of Layers that will be used in this article.

Constructing the HTML

To avoid any of the HTML being shown in browsers that do not support the features required by this Dynamic StyleSheet tool, we will output all the necessary HTML using JavaScript. This allows us to control when and where the HTML is shown.

The following JavaScript outputs the controls used in the working example. Don't worry too much about the contents, accept to see that firstly it will only be used in JavaScript 1.2 enabled browsers, secondly it tests for the existence of either the document.styleSheets or the document.layers objects.

The document.styleSheets object was introduced in Explorer version 4, as a means to access any and all of the style sheets in the current document. The document.layers object was introduced in Navigator version 4 along with Layers. Rather than detect what browser is being used, we detect what functionality the browser supports.

If the browser supports document.styleSheets then we only need to output some sample HTML, if the browser does not support document.styleSheets but supports document.layers then rather than output some sample HTML, we need to include several versions of the same HTML using either <LAYER> or <ILAYER>.

The document.styleSheets object allows dynamic alteration of various styles without the need to reload the document. If we simply used plain sample HTML when using Navigator we would need to reload the page each time a style changed to see the effect. With the aid of layers we can preload different verions of the HTML each with the required style already set. When we need to show one style over another we simply hide all the previous Layers, and reshow the required Layer.

When using the <LAYER> and </LAYER> tags, the contents are not inline with the rest of the document, i.e. they can be overlapped with other HTML elements. To reserve space in the document for a Layer we need to use the alternative inline Layer <ILAYER> and </ILAYER> tags.

When we want to show more than one Layer in a particular spot of a document, but where we wish to swap between other hidden Layers, only one of the Layers, the last, should use the alternative inline Layer tags.

<HEAD>
<TITLE>Customise page</TITLE>
<SCRIPT LANGUAGE="JavaScript1.2" SRC="library.js"></SCRIPT>
</HEAD>

<BODY>

<SCRIPT LANGUAGE="JavaScript1.2"><!--
if (document.styleSheets || document.layers) {
    document.write('<P>Please browse available styles using the box below, and confirm your choice by pressing the OK button.');
    document.write('<FORM>');
    document.write('<SELECT NAME="style" onChange="changeSheet(this.selectedIndex)">');
    document.write('<OPTION>Style 1<\/OPTION>');
    document.write('<OPTION>Style 2<\/OPTION>');
    document.write('<OPTION>Style 3<\/OPTION>');
    document.write('<\/SELECT>');
    document.write('<INPUT TYPE="BUTTON" VALUE="OK" onClick="Set_Cookie(\'stylesheet\',mySheet,expires)">');
    document.write('<\/FORM>');

    if (document.styleSheets) {
        document.write('<H1>Headings will appear like this.<\/H1>');
        document.write('<P><A HREF="javascript:alert(\'just testing\')">Links will appear like this.<\/A>');
        document.write('<P><CODE>Any quoted code will appear like this.<\/CODE><BR>');
    }
    else if (document.layers) {
        document.write('<LAYER SRC="style1.htm" NAME="style1" VISIBILITY="show"><\/LAYER>');
        document.write('<LAYER SRC="style2.htm" NAME="style2" VISIBILITY="hide"><\/LAYER>');
        document.write('<ILAYER SRC="style3.htm" NAME="style3" VISIBILITY="hide"><\/ILAYER>');
    }

    checkStyle();
}
//--></SCRIPT>
</BODY>
</HTML>

Now that's out of the way, we can look at the form being generated in the above code. The selectedIndex property of the selection box returns a number between 0 and 2 (because there are 3 options). Therefore we pass a value corresponding to the selected option to the changeSheet() function. When the OK button is clicked the Set_Cookie() function is called to store a cookie with the details of the selected Style Sheet. The function is passed the name of the cookie to be stored stylesheet, the value of the cookie held in mySheet and the date it will expire held in expires - all detailed later.

In the above code each of the three layers has a SRC, NAME and VISIBILITY attribute. The SRC attribute loads the file reference as the contents of the Layer, the NAME attribute enables us to refer to the Layer using JavaScript, the VISIBILITY attribute controls where the Layer is hidden ('hide') or visible ('show').

The code above also loads a JavaScript source file library.js which contains the source code of all the JavaScript functions referred to in the code.

The JavaScript Functions

Using a JavaScript Source file enables us to keep all the JavaScript needed to support the Dynamic Style Sheets in one single file. We can then include a reference to it in all are other web pages. The contents of library.js is described below.

First, we'll need some code to read and write the cookie.

The two cookie functions Get_Cookie() and Set_Cookie() are as described in the Chocolate Chip Cookies article.

function Get_Cookie(name) {
    var start = document.cookie.indexOf(name+"=");
    var len = start+name.length+1;
    if ((!start) && (name != document.cookie.substring(0,name.length))) return null;
    if (start == -1) return null;
    var end = document.cookie.indexOf(";",len);
    if (end == -1) end = document.cookie.length;
    return unescape(document.cookie.substring(len,end));
}

function Set_Cookie(name,value,expires,path,domain,secure) {
    document.cookie = name + "=" +escape(value) +
        ( (expires) ? ";expires=" + expires.toGMTString() : "") +
        ( (path) ? ";path=" + path : "") + 
        ( (domain) ? ";domain=" + domain : "") +
        ( (secure) ? ";secure" : "");
}

The expiration date of our cookie is set to the value of the expires variable, which is set to 365 days from now:

var expires = new Date();
expires.setTime(expires.getTime() + (365 * 24 * 60 * 60 * 1000 * 365));

Here is that global definition of the mySheet variable. It originally holds the value of the stylesheet cookie.

mySheet = Get_Cookie('stylesheet');

if (mySheet != null)
    document.write('<LINK REL="stylesheet" HREF="' + mySheet + '.css">');
else
    document.write('<LINK REL="stylesheet" HREF="style1.css">');

Very simply, this runs the Get_Cookie() function (using the cookie called 'stylesheet'). If the results of that function are not equal to null, i.e. they are equal to something and therefore the cookie exists, then a Style Sheet is loaded based on the value of the 'stylesheet' cookie, otherwise the style1.css style sheet is loaded by default.

The following checkStyle() function determines which style is supposed to be shown based on the value of the mySheet variable. If it is null, then the Style Sheet is left alone. For browsers that support the document.styleSheets we change the href of the documents first styleSheets object, using either style1.css or style2.css or style3.css. For browsers that support the documents.layers all the Layers are first hidden, then the required Layer is shown.

function checkStyle() {
    if (mySheet != null) {
        if (document.styleSheets)
            document.styleSheets[0].href = mySheet + '.css';
        else if (document.layers) {
            document.layers['style1'].visibility = 'hide';
            document.layers['style2'].visibility = 'hide';
            document.layers['style3'].visibility = 'hide';
            document.layers[mySheet].visibility = 'show';
        }
    }
}

The purpose of the following changeSheet() function is to check what the user has selected in the selection box, and then change the documents styleSheet . This means we need to take the currently selected value of the selection box as a parameter (this.selectedIndex because we are referring to it from inside its HTML code). The function also sets the value of the global variable mySheet so that when the cookie is written, it saves the details of the current Style Sheet being shown.

function changeSheet(choice) {
    if (choice == 0) mySheet = 'style1';
    if (choice == 1) mySheet = 'style2';
    if (choice == 2) mySheet = 'style3';

    if (document.styleSheets)
        document.styleSheets[0].href = mySheet + '.css';
    else if (document.layers) {
        document.layers['style1'].visibility = 'hide';
        document.layers['style2'].visibility = 'hide';
        document.layers['style3'].visibility = 'hide';
        document.layers[mySheet].visibility = 'show';
    }
}

Test HTML

Well we've described the selection page and the JavaScript source code, but how do we use it on our other pages.

Simple, all we need to do is add a reference to the JavaScript source file library.js as in the following HTML:

<HTML>
<HEAD>
<TITLE>Test page</TITLE>

<SCRIPT LANGUAGE="JavaScript1.2" SRC="library.js"></SCRIPT>

</HEAD>

<BODY>

<H1>This is the test page</H1>

<P>Return to the <A HREF="custom.htm">custom page</A> or return to the <A HREF="index.htm">article</A>

<P><CODE>"Too many cooks spoil the broth"</CODE><BR>

</BODY>
</HTML>

Source Code

You can view the source code of the HTML components:

You can view the source code of JavaScript source file:

You can also view the source code of CSS files:

Working Example

Click here for a working example of the source code.

Conclusion

Dynamic Style Sheets can give us many new ideas to jazz up our Web sites. As well as what I've done in this article, you could have a different style every day of the week, or you could change the contents of individual STYLE tags on your page to alter only certain areas. There are countless possibilities.

Related items

Why use CSS?

An Introduction to Cascading Style Sheets

Feedback on 'Dynamic StyleSheets'

©2018 Martin Webb