Cascading Style Sheets, level 1 (CSS1), is a W3C Recommendation supported by Navigator 4.x, Internet Explorer and Gecko layout engine implemented in Netscape 6 and Mozilla browsers, which enables you to control the style (the format, or look and feel) of HTML elements using CSS1 markup. Because CSS1 rules are static and hard-coded, conditional style rules must be defined from JavaScript. This TechNote explains how to define CSS1 rules from JavaScript in a way that will work on Navigator 4.x, Netscape 6, Mozilla and Internet Explorer. It also provides a tool that automatically generates JavaScript code that defines CSS1 rules and runs on all three browsers.
Before reading this TechNote, you need to understand the syntax of CSS1 rules. In particular, you need to know how to select elements (with selectors like "P" for element names, "#someid" for ID attribute values, ".someclass" for CLASS attribute values, and ".someclass P #someid" for contextual selection), what the CSS1 property names are (such as "font-size" and "color"), and what the CSS1 property values are (such as "14pt" and "red").
If you need a basic introduction to CSS1, click through Netscape's Visual Tutorial on CSS1 on the Dynamic HTML Presentations Page. Tutorials available elsewhere on the web are listed on Netscape's Dynamic HTML Additional Resources Page. For full details, see the CSS1 Recommendation on the W3C Technical Reports Page.
If you don't know how to detect whether the user is using Navigator 4.x, Netscape 6 or Internet Explorer, read the Ultimate JavaScript Client Sniffer to learn how.
To learn how to access CSS1 properties from JavaScript in Navigator 4.x, click through Netscape's Visual Tutorial on Accessing CSS Properties from JavaScript via the Document Object Model on the Dynamic HTML Presentations Page.
Netscape enthusiastically supports CSS1 and recommends that you use CSS1 markup whenever possible to define the style of your web page. It is easy to maintain and works across Navigator 4.x, Netscape 6, Mozilla and Internet Explorer. (Note: Since Navigator 4.x and Internet Explorer have not implemented every CSS1 property and since there are some differences in implementation and interpretation of the standard, use a third-party reference like Web Review's CSS1 Master Grid to confirm that a given property works on both browsers and all your target platforms. Gecko layout engine implemented in Netscape 6 and Mozilla supports all of CSS1 properties.)
However, CSS1 markup has one fundamental limitation. It is completely static and hard-coded. You cannot conditionally set element properties using CSS1. For example, you can't check the current screen size and then adjust element font sizes up or down to match the screen size. To do that, you must define CSS1 rules from JavaScript.
Remember this rule of thumb: "What you can do with CSS1, do with CSS1. What you can't do with CSS1, do with JavaScript." In other words, if the value is static and never need change, set it with CSS1 markup. If the value is conditional, set it with JavaScript.
Navigator 4.x, Netscape 6, Mozilla and Internet Explorer make CSS1 properties of elements accessible from JavaScript through their Document Object Model (DOM). However, the Navigator 4.x DOM and Internet Explorer DOM are different. They both implement parts of the W3C CSS1 standards but they cover different areas, so JavaScript code that defines CSS1 rules on one browser won't work on the other browsers. Gecko layout engine covers all of the properties in W3C CSS1 standards.
To define CSS1 rules from JavaScript and have them work compatibly across Navigator 4.x, Netscape 6, Mozilla and Internet Explorer, you must do four things:
<STYLE ID="tssxyz" TYPE="text/css"></STYLE> <SCRIPT LANGUAGE="JavaScript1.2"><!-- var agt=navigator.userAgent.toLowerCase(); if ( (parseInt(navigator.appVersion)==4) && (agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1) && (agt.indexOf('compatible') == -1) ) { document.tags.P.fontSize="25pt"; } else if (agt.indexOf('gecko') != -1) { document.getElementById('tssxyz').sheet.insertRule('P { fontSize: 25pt }', document.getElementById('tssxyz').sheet.cssRules.length ) } else if ( (parseInt(navigator.appVersion)>=4) && (agt.indexOf('msie') != -1) ) { document.styleSheets["tssxyz"].addRule ("P", "fontSize:25pt"); } //--></SCRIPT> |
To map CSS1 rules to Navigator
4.x, Netscape 6, Mozilla and Internet Explorer JavaScript, you must
understand the structure of CSS1 rules. CSS1 rules have three parts: a
selector which chooses one or more elements on the page based on their
tag name, ID attribute value, CLASS attribute value, CLASS and name, or
context; a property name like "font-size"; and a value for the property,
such as "24pt." Here is the structure of a CSS1 rule with examples of the
five kinds of selectors and a property name and value:
Part of Rule | (kind of selector) | Example |
---|---|---|
selector | tag name: | "P" |
class: | ".warning" | |
ID: | "#foo" | |
class and tag name: | "P.warning" | |
contextual: | "P B.warning #foo" | |
property name | "font-size" | |
value | "24pt" |
To detect which browser the user is using, use the JavaScript browser-detect code in The Ultimate JavaScript Client Sniffer.
To define CSS1 rules from JavaScript in Navigator 4.x, there are two steps:
CSS1 selectors are mapped to Navigator 4.x JavaScript selectors as follows:
Mapping CSS1 Selectors to Navigator 4.x JavaScript Selectors | ||
---|---|---|
Type of selector | CSS1 example | JavaScript equivalent |
tag name | "P" | document.tags.P |
class | ".warning" | document.classes.warning.all |
identifier | "#foo" | document.ids.foo |
tag name and class | "P.warning" | document.classes.warning.P |
contextual | "P B.warning #foo" | document.contextual (document.tags.P,document.classes.warning.B, document.ids.foo) |
Mapping CSS1 Property Names to JavaScript Property Names
Mapping CSS1 property names to JavaScript property names is easy. You drop the hyphens and change each character after a hyphen to uppercase. For example, the CSS1 property name "font-size" becomes the JavaScript property name "fontSize".
The only exception is properties that take multiple values. These are mapped to methods which have a trailing "s" after their names. For example, border-width becomes borderWidths(), margin becomes margins(), and padding becomes paddings().
Example of Mapping CSS1 Rule to Navigator 4.x JavaScript
As an example, this CSS1
rule:
P { font-size: 25pt } |
...becomes this JavaScript
command in Navigator 4.x:
document.tags.P.fontSize="25pt"; |
To define CSS1 rules from JavaScript in Netscape 6 and Mozilla, there are two steps:
<STYLE ID="tssxyz" TYPE="text/css"></STYLE> |
The ID "tssxyz" stands for "Target Style Sheet," with "xyz" added to increase the "uniqueness" of the identifier and reduce the likelihood that it would collide with an ID anyone else has used already.
The Gecko
insertRule
method has this syntax:
document.getElementByID(targetSheetID).sheet.insertRule (selector + "{" propName + ":" + value + "}", locationOfRule); |
In order to add the CSS1
rule to the end of the target style sheet, set the location of the rule
in the style sheet to:
targetSheetID.cssRules.length |
For example, this CSS1 rule:
H1 { color: red } |
...becomes this JavaScript
command in Netscape 6 and Mozilla:
document.getElementById("tssxyz").sheet.insertRule("H1 { color: red }", tssxyz.cssRules.length); |
To define CSS1 rules from JavaScript in Internet Explorer, there are two steps:
<STYLE ID="tssxyz" TYPE="text/css"></STYLE> |
The ID "tssxyz" stands for "Target Style Sheet," with "xyz" added to increase the "uniqueness" of the identifier and reduce the likelihood that it would collide with an ID anyone else has used already.
The Internet Explorer
addRule
method has this syntax:
document.styleSheets[targetSheetID].addRule (selector, propName + ":" + value); |
As an example, this CSS1
rule:
P { font-size: 25pt } |
...becomes this JavaScript
command in Internet Explorer:
document.styleSheets["tssxyz"].addRule ("P", "fontSize:25pt") |
To achieve the same result, the rules must be added by JavaScript at the same place in the HTML markup in the same order. This will make sure they get the same CSS1 priority level in Internet Explorer, Navigator 4.x, Mozilla and Netscape 6. (Later rules have higher priority.)
Obeying these three rules will ensure that rules are added at the same position in the document in the same order across both browsers:
<STYLE ID="tssxyz" TYPE="text/css"></STYLE> <SCRIPT LANGUAGE="JavaScript1.2"> var agt=navigator.userAgent.toLowerCase(); if ( (parseInt(navigator.appVersion)==4) && (agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1) && (agt.indexOf('compatible') == -1) ) { document.classes.hint.all.backgroundColor="yellow"; } else if (agt.indexOf('gecko') != -1) { document.getElementById('tssxyz').sheet.insertRule('.hint { background-color: yellow }', document.getElementById('tssxyz').sheet.cssRules.length ) } else if ( (parseInt(navigator.appVersion)>=4) && (agt.indexOf('msie') != -1) ) { document.styleSheets["tssxyz"].addRule (".hint", "background-color:yellow"); } </SCRIPT> |
One CSS1 property to pay special attention to for cross-browser compatibility is backgroundColor, because Navigator 4.x hasa significant difference in its implementation of this property then Internet Explorer, Netscape 6 and Mozilla. Navigator 4.x displays an element's background color only behind the element's text. Internet Explorer, Netscape 6 and Mozilla display the background color all the way to the right edge of the screen.
For example, this markup:
<P STYLE="background-color: red">red background></P> |
... looks like this in Navigator 4.x:
red background of P looks like this in Navigator 4.x
...and looks like this in
Internet Explorer, Netscape 6 and Mozilla:
red background of P looks like this inInternet Explorer, Netscape 6 and Mozilla |
To make the background
color behind only the element's text in all three browsers, set
background color on a <SPAN> enclosing
the text. For example, this markup:
<P><SPAN STYLE="color:white; background-color:black"> white on black behind text in all three browsers </SPAN></P> |
...will produce this result in all browsers:
white on black behind text only in both browsers
To make the background color
to the right edge of the page in all three browsers, use 1x1 TABLE
element with
WIDTH=100%. For example, this
markup:
<TABLE WIDTH=100%> <TR><TD STYLE="color:white; background-color:black"> <SPAN STYLE="color:white; background-color:black"> white on black to right edge of page in all three browsers </SPAN> </TD></TR> </TABLE> |
...will produce this result in all browsers:
white on black to right edge of page in all browsers |
For a positioned HTML element
that covers a rectangular area, to make the background color behind the
entire element area (regardless of the amount of text), use a 1x1 borderless
table with WIDTH and HEIGHT and background properties set to match element.
For example, this markup:
<STYLE TYPE="text/css"> #samplerect { position: relative } </STYLE> <DIV ID="samplerect" STYLE="width: 500px; height: 60px; background-color: red"> <TABLE WIDTH=500 HEIGHT=60 STYLE="background-color: red"> <TR><TD>some text that doesn't fill the element</TD></TR> </TABLE> </DIV> |
...will produce this result in all browsers:
some text that doesn't fill the element |
The free tool in this TechNote automatically generates JavaScript code that defines CSS1 rules and works on Navigator 4.x, Netscape 6, Mozilla and Internet Explorer. All you have to do is type the CSS1 selector, property name, and value (which together define a CSS1 rule) into the form and click "Generate Code." The form will automatically convert the CSS1 rule into HTML and JavaScript which works on all three browsers. You can then copy and paste the generated STYLE and SCRIPT elements into the HEAD of your HTML page, and the elements' CSS1 properties will be set from JavaScript on both browsers. (Make sure to copy and paste all of the markup, including the empty STYLE element which is generated to make the code work on Netscape 6, Mozilla and Internet Explorer! )
Usually, you will use this tool in one of two ways: setting a CSS1 property to the value of a variable, or conditionally evaluating JavaScript style code. (These are both things which cannot be done using static CSS1 markup.) You can also create JavaScript commands which set CSS1 properties to fixed, unchanging, hard-coded values, but in that case, you might as well use CSS1 markup instead of JavaScript.
Setting a CSS1 Property to the Value of a Variable
The easiest way to use this tool is to define a JavaScript variable that holds the value you want to use for some CSS1 property. The JavaScript code that determines the value can be as sophisticated as you wish. Usually, it will be a series of if statements.
For example, to create a paragraph P element that uses the same amount of screen space regardless of the current display size, you could determine the font size of the P element in points (pt) as follows:
if (screen.width < 700) pFontSize="22pt"; else if (screen.width < 900) pFontSize="28pt"; else pFontSize="36pt"; |
This "initialization code" stores the font size you want to use for the P element in the variable pFontSize. You would paste this code into the "Initial JavaScript code" text area on this form. (We've done it for you in the sample below.)
Now you just need to create a rule that sets the font size for P elements to the JavaScript variable pFontSize. To do that, you create a rule using the form below. In a single row, you define the selector, property name, and value for that rule.
To create the rule "Set the font size for all P elements to the variable pFontSize," you would enter:
Conditionally Evaluating JavaScript Style Code
Sometimes you will want to check the value of a variable in an if or switch statement and then, depending on the value of the variable, evaluate or ignore one or more blocks of JavaScript style definitions. This tool won't generate the if statements for you, but you can generate all the rules and then fill in the if statements yourself.
For example, suppose that
you were displaying a weekly calendar and wanted today's day name to be
displayed in red text with all the other days of the week displayed in
the default color black. You could fill in the form's "Initial JavaScript
code" field with code to retrieve the current day:
var theDate = new Date(); var today=theDate.getDay(); |
Then you would fill in the
table with rules to set every day's color to red:
CSS1
Selector: |
CSS1
Property Name: |
CSS1
Value: |
---|---|---|
.sundayColor | color | red |
.mondayColor | color | red |
.tuesdayColor | color | red |
.wednesdayColor | color | red |
.thursdayColor | color | red |
.fridayColor | color | red |
.saturdayColor | color | red |
...and click "Generate Code"
to generate the JavaScript code for all the rules on both browsers automatically.
Then you would edit the code and add if statements to ensure that only
the rule for setting the color of today's day name is evaluated.
The finished code would look like this:
<STYLE ID="tssxyz" TYPE="text/css"></STYLE> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- var theDate = new Date(); var today=theDate.getDay(); var agt=navigator.userAgent.toLowerCase(); if ( (parseInt(navigator.appVersion)==4) && (agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1) && (agt.indexOf('compatible') == -1) ) { if (today==0) document.classes.sundayColor.all.color="red"; if (today==1) document.classes.mondayColor.all.color="red"; if (today==2) document.classes.tuesdayColor.all.color="red"; if (today==3) document.classes.wednesdayColor.all.color="red"; if (today==4) document.classes.thursdayColor.all.color="red"; if (today==5) document.classes.fridayColor.all.color="red"; if (today==6) document.classes.saturdayColor.all.color="red"; } else if (agt.indexOf('gecko') != -1) { if (today==0) document.getElementById('tssxyz').sheet.insertRule('.sundayColor { color: red }', document.getElementById('tssxyz').sheet.cssRules.length ); if (today==1) document.getElementById('tssxyz').sheet.insertRule('.mondayColor { color: red }', document.getElementById('tssxyz').sheet.cssRules.length ); if (today==2) document.getElementById('tssxyz').sheet.insertRule('.tuesdayColor { color: red }', document.getElementById('tssxyz').sheet.cssRules.length ); if (today==3) document.getElementById('tssxyz').sheet.insertRule('.wednesdayColor { color: red }', document.getElementById('tssxyz').sheet.cssRules.length ); if (today==4) document.getElementById('tssxyz').sheet.insertRule('.thursdayColor { color: red }', document.getElementById('tssxyz').sheet.cssRules.length ); if (today==5) document.getElementById('tssxyz').sheet.insertRule('.fridayColor { color: red }', document.getElementById('tssxyz').sheet.cssRules.length ); if (today==6) document.getElementById('tssxyz').sheet.insertRule('.saturdayColor { color: red }', document.getElementById('tssxyz').sheet.cssRules.length ); } else if ( (parseInt(navigator.appVersion)>=4) && (agt.indexOf('msie') != -1) ) { if (today==0) document.styleSheets["tssxyz"].addRule (".sundayColor", "color:red"); if (today==1) document.styleSheets["tssxyz"].addRule (".mondayColor", "color:red"); if (today==2) document.styleSheets["tssxyz"].addRule (".tuesdayColor", "color:red"); if (today==3) document.styleSheets["tssxyz"].addRule (".wednesdayColor", "color:red"); if (today==4) document.styleSheets["tssxyz"].addRule (".thursdayColor", "color:red"); if (today==5) document.styleSheets["tssxyz"].addRule (".fridayColor", "color:red"); if (today==6) document.styleSheets["tssxyz"].addRule (".saturdayColor", "color:red"); } //--> |
This test
page demonstrates that JavaScript generated by this code generator
works compatibly across both browsers for many CSS1 properties and values.
Netscape 4.74 crashes
when there is an empty style sheet in the <HEAD>. If you are using this
browser I would strongly suggest you to upgrade it to 4.76 or Netscape
6. You can find both of these browsers here.
If you would like to download
this TechNote (including the code generator) to your local machine, just
download this WinZIP-compatible
ZIP file with all of the necessary files.
For the latest technical information on Sun-Netscape Alliance products, go to: http://developer.iplanet.com
For more Internet development resources, try Netscape TechSearch.