DHTML
One of the most popular uses of JavaScript is DHTML (Dynamic HyperText Markup Language). Strictly speaking, DHTML is using JavaScript to modify the CSS styles of HTML elements. All current browsers support much more than I will describe at this stage of the tutorial. For now, I will concentrate on the capabilities introduced by 4th generation browsers. Old browser versions (such as Netscape 4 and Opera 6-) limit the abilities of '4th generation' DHTML, as these can only handle basic DHTML. However, they still provide easily enough flexibility to make features like pop-up menus, message scrollers, mouse trails or falling snow effects.
This requires parts of the page to move or appear/disappear. In current browsers, this can be done with any element, and in older browsers can be done reliably using the div element and in many cases the span element, when they are positioned using the position: absolute; or position: relative; style (except when changing the display style). Personally, I almost always use the div element and I can guarantee that it will work with everything I show you here. Some very old browsers (particularly Netscape 4) have problems using the span element when positioned absolutely.
Once you have set up the HTML (using a few workarounds for bugs), you can reference the positioned element. You can then use that reference to change the visibility, position, background colour, z-index, clipping and size of the positioned element. You can even rewrite the contents of the positioned element or create new positioned elements after the page has loaded. DHTML also allows you to change the background colour of the whole document and change the display style of ANY element.
Sadly, DHTML is always browser specific, in other words different browsers require different commands (though with current browsers supporting the DOM, it is often possible to use only that approach in current Web sites). Using the techniques I will show you, this is not difficult to work with, to make sure that no matter what syntax the browser expects, the script can check what to use, and use it correctly. Many authors make the mistake of detecting browsers and assuming capabilities, or detecting one capability and assuming another. This tutorial does not rely on these mistaken assumptions. At no point should you need to detect specific browsers.
4th generation browsers
There are several browsers that I know of that can handle DHTML (often called 'version 4' or '4th generation' browsers, even though their version number may not actually be as high or low as 4). The following list gives a different line for each significantly different browser. Some of these browser engines are used in a large number of other browsers. For example:
- The Internet Explorer (Win) engine is used in Maxthon, Avant, many AOL versions, and many others.
- The Gecko engine is used in Camino, K-Meleon, Flock, and many others.
- The Opera engine is used on a large number of mobiles and devices, in a variety of different applications.
- The KHTML/Webkit engine is used in Chrome, OmniWeb and several other browsers.
Major browsers
- Internet Explorer 5+ (Win)
- Uses document.getElementById and document.all
- Mozilla Gecko (FireFox, Netscape 6+)
- Uses document.getElementById (also secretly uses document.all)
- Opera 7+
- Uses document.getElementById and document.all (document.all is secretly supported in Opera 9.5+)
- KDE KHTML/WebKit (Safari, Chrome, Konqueror 3+, OmniWeb 4.5+)
- Uses document.getElementById (Chrome/Safari 3 also secretly uses document.all)
Minor browsers
These browsers are not used very much, or are no longer the current versions of these browsers. Some may have significant bugs, limited capabilities, or limited event detection.
Several of these use the Mozilla Organization's Java based Rhino JavaScript engine to power their browsers. The Rhino JavaScript engine only powers the JavaScript language interpreter, it does not govern how JavaScript interacts with the web page. Each browser will have its own DHTML (or DOM) implementation.
- (Internet) Explorer 5 (Mac)
- Uses document.getElementById and document.all
- iCab 3
- Uses document.getElementById and document.all
- Internet Explorer 4 (Win)
- Uses document.all
- (Internet) Explorer 4 (Mac)
- Uses document.all
- Opera 5-6
- Uses document.getElementById
- Mozilla Rhino engine (ICEbrowser)
- Uses document.getElementById and document.all
- Mozilla Rhino engine (Escape/Evo 5)
- Uses document.getElementById and document.all
- Mozilla Rhino engine (Escape 4)
- Uses document.layers
- Mozilla Rhino engine (Clue browser)
- Uses document.getElementById and document.all
- Tkhtml+EES (Tkhtml Hv3)
- Uses document.getElementById
- Netscape 4
- Uses document.layers
- OmniWeb 4.2-
- Uses document.layers (also optionally supports document.all)
- iCab 2
- Uses document.getElementById and document.all
- Konqueror 2
- Uses document.getElementById and document.all
Television or mobile device browsers
Due to the limitations of the devices that these browsers run on, most will have limited event detection. Several popular browsers engines are also used in mobile/TV browsers, including Opera, WebKit and Gecko. Others use their own engines, and are given below:
- NetFront
- Uses document.getElementById
- Pocket Internet Explorer
- Uses document.all and document.getElementById in newer versions
- Netgem 4 browser (NetBox)
- Uses document.getElementById
- OpenTV
- Uses document.getElementById
- iPanel MicroBrowser with advanced modules
- Uses document.getElementById
- WebTV (MSN TV) Plus and extended Classic
- Uses document.all (and non-nested layers alternative)
More information
For more details of these browsers, and to download them, please see my list of '4th+ generation' browsers.
(You can also try this site for a fairly complete list.)
While many JavaScript and DHTML functions worked in Konqueror 2, the browser was unable to detect and handle events properly so most DHTML applications did not work. Konqueror 3 is a big improvement and is now a highly capable browser, so I have given compatibility notes for Konqueror 3+ only.
I am unsure of the abilities of NetBox, iPanel MicroBrowser and OpenTV as I do not have them to test. The NetBox site claims partial CSS 2, so I assume CSS positioning, and W3C DOM 1, so I assume DHTML. OpenTV claims absolute CSS positioning and DOM DHTML. The EIS claims that one of their advanced modules for iPanel MicroBrowser can handle DOM. They might not support innerHTML because that is not part of the DOM standard, even though it has been widely accepted by almost all DOM browsers.
Note that even though Escape 4 is a layers browser, like Netscape 4, it supports both the Netscape syntax and the style object for changing element style, with the exception of clipping. WebTV 2.8+ also supports both syntaxes, but is a proprietary DOM browser.
Setting up the HTML
There are two types of positioning that are of interest here. These are absolute and relative. Absolute allows you to position an element anywhere you want to, in relation to the page. Relative positions the element where it normally would be, and offsets it by whatever amount you specify.
Most DHTML is done with absolutely positioned elements. Relatively positioned elements do not accept the 'clip' style and do not allow their clipping to be changed. The useful feature of relatively positioned elements is that they become containers for absolutely positioned elements. So if you put an absolutely positioned element inside a relatively positioned element, its position will be in relation to the relatively positioned element, and not the whole page.
You can create an absolutely positioned elements using this:
<div id="mydiv" style="position: absolute; left: 10px; top: 120px;">contents</div>
And you can create an relatively positioned elements using this:
<div id="mydiv" style="position: relative; left: 10px; top: 120px;">contents</div>
The ID is important, because that is what will be used to reference the positioned element. Layers browsers call these positioned elements 'layers'.
Bugs / workarounds
If using document.write to create the positioned element, Netscape 4 will fail to load the page. Netscape 4 is not
important any more, so I suggest you ignore it. If you really need to support it, you can use the unofficial
<layer ...>
tag instead of an absolutely positioned div, and the unofficial
<ilayer ...>
tag instead of of a relatively positioned div. Use
if( document.layers )
to find out if you need to.
Similarly in Netscape 4, setting any styles using inline style attributes on elements inside a positioned element will cause the page not to load. Instead, create a class for the elements and style them in the main stylesheet.
Referencing the positioned element
- iCab 2- does not support positioning, but it can still reference the unpositioned element.
To reference a positioned element, there are several ways. The official one is a standard called the W3C DOM. It is supported well enough by all current browsers. There are also two alternatives for the few old browsers that may still be in use. One of these techniques has two different versions.
DOM
DOM browsers use the document.getElementById method to reference the element. You can use a simple if statement to check for the existence of this method. In all current browsers, this will be supported, so in the majority of current scripts, you can simply assume it is supported, and ignore the other approaches.
if( document.getElementById ){
var myReference = document.getElementById('divID');
}
Proprietary DOM
Proprietary DOM browsers use the document.all collection to reference the element. Some browsers support both the DOM and proprietary DOM for referencing elements.
if( document.all ){
var myReference = document.all['divID'];
}
Layers
Layers browsers use the document.layers collection to reference the element. Layers in the layers collection can be accessed using either their ID or their numerical index. They will also be able to reference the element through document.divID (where divID is the id that you gave the div). Netscape 4 was the main layers browser, and was the first browser capable of performing DHTML. However, the layers approach has been abandoned by current browsers.
if( document.layers ){
var myReference = document.layers['divID'];
}
Layers also have one behaviour that sets them apart from the other approached, and can make them difficult to write for. If a positioned element is inside another positioned element, the inner one does not appear inside the layers collection of the document. Instead, it appears inside the layers collection for the document object of the outer layer. This means that that to reference any layer by its ID, you must recursively step through every layers collection in the document, until you find the right one. Since ID attributes must be unique within a document anyway, this approach is needlessly convoluted, which is one of the reasons why it was abandoned.
Combining the approaches
The three techniques can be combined into a single function, that will use the DOM method if it is available. Failing that, it will use the proprietary DOM, and failing that, layers. If it fails to find it in the document's layers collection, it steps through the entries in the collection, and checks the layers collection of each of those, and continues recursively.
function getRefToDiv(divID,oDoc) {
if( document.getElementById ) {
return document.getElementById(divID); }
if( document.all ) {
return document.all[divID]; }
if( !oDoc ) { oDoc = document; }
if( document.layers ) {
if( oDoc.layers[divID] ) { return oDoc.layers[divID]; } else {
//repeatedly run through all child layers
for( var x = 0, y; !y && x < oDoc.layers.length; x++ ) {
//on success, return that layer, else return nothing
y = getRefToDiv(divID,oDoc.layers[x].document); }
return y; } }
return false;
}
Changing the visibility
- iCab 2- does not support visibility.
- OmniWeb 4.2- frequently makes mistakes with visibility.
- Many device browsers will ignore visibility when in small screen reformatting mode.
Changing the visibility style allows you to make a positioned element appear and disappear. It can be set to either 'visible' or 'hidden'. Layers browsers use 'show' and 'hide'. There are some layers browsers that support both versions. The code here will detect what is supported and use it, instead of detecting one thing and assuming something else.
Once you have referenced the positioned element, you will need to reference its style. In non-layers
browsers, you will have to add '.style
' to the end of the reference. Layers browsers treat the styles as
direct properties of the element itself. To work out which one to use, simply check for the existence of the
style property. You can then set the relevant value:
So, after all of that, a full set of instructions to make a positioned element visible would be:
function showDiv(divID_as_a_string) {
//get a reference as above ...
myReference = getRefToDiv(divID_as_a_string);
if( !myReference ) {
window.alert('Nothing works in this browser');
return; //don't go any further
}
//now we have a reference to it
if( myReference.style ) {
//DOM & proprietary DOM
myReference.style.visibility = 'visible';
} else {
//layers syntax
myReference.visibility = 'show';
}
}
showDiv('myDiv');
... ...
<div style="position:absolute;left:0px;top:0px;" id="myDiv">
contents
</div>
Test it here: show the hidden element.
This positioned element was hidden. Hide it again.
Of course, don't actually alert the message 'Nothing works in this browser', instead, offer them an alternative that does not require the fancy script.
Changing the position
- iCab 2- does not support positioning.
- OmniWeb 4.2- does not understand relative positioning and makes mistakes with absolute positioning.
- WebTV can only change horizontal position, not vertical.
- Clue browser sometimes only allows horizontal position to be changed, and sometimes does not allow positions to be changed at all.
You can adjust the position by using left or top the same way as we used visibility above, and then specifying the position in pixels. (Note, this top is not the same as the window.top mentioned in the section on frameset references.) In order to retrieve the left and top properties as I am about to do, the left and top styles must have been set using the inline style syntax, or by being initially set with JavaScript.
When a strict doctype is used, many browsers require you to use the correct units (20px, not 20), but many older browsers do not understand this, such as Opera 5 ('top' only), layers browsers, WebTV etc. There is no direct way to detect if a browser understands the units or not, since it may accept the values, even if it does not support them. For this reason, I detect document.childNodes, as this is one of the basic requirements for proper DOM support. DOM style requires units to be used, and therefore all browsers that understand DOM also understand the units.
In this example, left and top are both initially set to 10px using an inline style attribute. The code will check if
it needs to use a '.style
' reference, and if so, it will change the reference the style object instead,
allowing the style to be changed for all versions in just one step. It will then retrieve the current positions,
add on the new amount and set that as the new position. When it retrieves the current value, it uses parseInt, because
the value may contains the units, depending on the browser.
<div style="position:absolute;left:10px;top:10px;" ...
... ...
var noPx = document.childNodes ? 'px' : 0;
if( myReference.style ) { myReference = myReference.style; }
myReference.left = ( parseInt(myReference.left) + 10 ) + noPx;
myReference.top = ( parseInt(myReference.top) + 20 ) + noPx;
The div will move 10 pixels down, and 20 pixels to the right. It will now be at coords - top: 30px; left: 20 px;
Test it here: move this element.
This can quite easily be used along with a timer which fires every few
milliseconds and repositions a positioned element according to the
scrolling offset to make the element appear static on the screen
(position:fixed;
is preferred, however).
Changing the background colour
- Old Gecko browsers have bugs that are easily avoided. See my Gecko engine mouseout bug documentation.
- WebTV and OmniWeb 4.2- do not allow you to change the background colour.
It would be nice to change the text colour as well, but layers browsers cannot do that. To change the background colour, there are three ways. Layers browsers use bgColor. DOM and proprietary DOM browsers can use background and backgroundColor. Opera 5.x can only change the background style, all the others (including Opera 6+) can change both. 'myReference' must be obtained as above. Note; some versions of Opera 5 will only change the background colour if it has already been explicitly defined, and is not inherited.
Warning, Opera 7-7.1 will return the string 'Warning' if you check for bgColor - so if you are checking for which one to change, you must put that syntax last.
if( myReference.style ) { myReference = myReference.style; }
if( myReference.background ) {
//supported by most browsers
//like Gecko browsers and the IE series
myReference.background = '#00ff00';
} else if( myReference.backgroundColor ) {
//supported by most browsers
myReference.backgroundColor = '#00ff00';
} else if( myReference.bgColor ) {
//used by layers browsers
myReference.bgColor = '#00ff00';
} else {
//FAILURE, there is no way to change the background colour
}
As setting the wrong one will not cause any problems, this can be easily simplified to:
if( myReference.style ) { myReference = myReference.style; }
myReference.bgColor = '#00ff00';
myReference.background = '#00ff00';
myReference.backgroundColor = '#00ff00';
Test it here: change the background colour of this element.
Changing the z-index
- iCab 2- does not support positioning so cannot support z-index.
- WebTV and Clue browser do not support z-index.
The z-index of positioned elements defines what order they should be stacked above each other. The z-index should be a positive integer. The higher the z-index, the more positioned elements it will be stacked on top of. Two elements must not be given the same z-index. To read the z-index of a positioned element, it must be already defined using the inline style syntax.
if( myReference.style ) { myReference = myReference.style; }
myReference.zIndex = 100;
Test it here: Click the link in each positioned element to raise its z-index above the z-index of the other element.
Changing the clipping
- Opera 6-, Konqueror 3.0-, OmniWeb 4.2-, WebTV, NetFront 3.3-, iCab 2- and Tkhtml Hv3 do not support clipping (iCab 2- does not support positioning so cannot support clip).
- Internet Explorer 7- does not follow current standards when using "standards rendering mode", and needs special attention, as shown below.
- In Opera 7-7.1 (fixed in later releases), the background colour shows through the clipping on clipped elements. The solution is to clip one element and hold a coloured element inside it.
- Although Escape 4.x supports the style object, it does not support the style.clip syntax.
Clipping can only be used on absolutely positioned elements.
This technique is usually used for message scrollers. In browsers that do not support clipping, it is possible to provide them with an iframe so that the contents of that can be scrolled. Please see my scroller example for a more detailed explaination of what clipping is and how it works.
You may want to check that the element can be clipped (there is no real need to, as browsers that do not understand it will just ignore you). This is very difficult as browsers like Opera 6- will give 'rect()' if asked for the clip style but have no way of using it. I have found no good way to do this. The best I can do is to check if myReference.innerHTML and myReference.clip are supported. I do not know of any browsers that should have problems with this as they support innerHTML but not clipping, but do give 'rect()' if asked for the clip style. However, setting the clipping in browsers that do not support it will not cause errors, it just has no effect. As Escape supports the style object but does not support the style.clip syntax, it is important to make sure it uses the clip object instead, so this is put first.
if( myReference.clip ) {
myReference.clip.left = 0;
myReference.clip.top = 0;
myReference.clip.right = 10;
myReference.clip.bottom = 10;
} else if( myReference.style ) {
//top right bottom left
myReference.style.clip = 'rect(0px,10px,10px,0px)';
} else {
//FAILURE, nothing works
}
Test it here: select a clipping rectangle for the positioned element below. The background shows through wherever the clipping hides parts of the element:
Line one of the positioned element. Your browser does not support clipping.
Line two of the positioned element.
Background Background Background
Background Background Background
Note that although the CSS 2.1 standard requires browsers to support rect()
with commas between
parameters, Internet Explorer 6 and 7 do not apply the rule if it contains commas, if the page's DOCTYPE triggers
"standards rendering mode". (This is due to a mistake in the CSS 2.0 specification.) Note that
this only applies when the style is set with a stylesheet; if set with a script, it will work with the correct syntax.
To avoid this problem, simply set the style twice in the stylesheet, once with commas, and once without. Browsers will
use whichever version they understand.
Changing the size
- WebTV cannot change element size.
- Escape/Evo 5 will produce errors because I check for document.childNodes.
- ICEbrowser will change element size, but may not show any change until the browser window is resized.
- iCab 2- produces strange overlaps when changing size because it does not support positioning.
- In Clue browser, the element may just disappear.
Layers browsers expect you to use the resizeTo method, while a few browsers expect you to change the pixelWidth and pixelHeight properties of the style object. All other browsers expect you to change the height and width properties of the syle object. You can set these last two anyway, reguardless of what the browser exects, because the browser will just ignore them. Some browsers will not re-arrange the contents of the element to suit the new size. In layers browsers, this is equivalent to setting clip.bottom and clip.right, which are the properties that should be read to get the current size. Although this is not accurate as the layer could extend beyond either of these clips, it is the best that layers browsers provide. To change only width or height in layers browsers, you must change the right or bottom properties of the clip object.
Some browsers will not shrink the element smaller than its contents. Some will clip the contents to the new size. Some will rearrange the contents to fit the new size. Some will shrink the element but leave the contents as they were, still visible.
As with element position, some older browsers do not like to have the units (px) written after the size, while newer browsers require it for strict doctypes. Again, a quick detect sorts the good browsers from the not-so-good.
if( myReference.style ) { myReference = myReference.style; }
if( myReference.resizeTo ) {
myReference.resizeTo( newWidth, newHeight );
}
var noPx = document.childNodes ? 'px' : 0;
myReference.width = newWidth + noPx;
myReference.pixelWidth = newWidth;
myReference.height = newHeight + noPx;
myReference.pixelHeight = newHeight;
Try it here: select a new size for the element:
Test
Test
Rewriting the contents
- Opera 6- and OmniWeb 4.2- cannot rewrite the contents of positioned elements.
- WebTV may just crash.
- Layers browsers can only rewrite the contents of absolutely positioned elements.
- Netscape 4 loses style in positioned elements when their contents are rewritten.
- In Clue browser, the element may just disappear, along with the document below it.
This functionality has been completely replaced in the W3C DOM, using various methods. The old DHTML approach should not be used in any new Web pages, and is best removed and replaced with DOM functionality (or innerHTML, which has now been standardised, and supported by all current browsers). It is retained here to allow it to be recognised.
In the following example, myReference is obtained as before. Most browsers provide the innerHTML property, which you can rewrite with the new HTML. Layers browsers allow you to use the methods open, write and close on the document object of the layer. Some browsers (like Opera) will also provide the document property of the positioned element, but that is a reference back to the main document. Rewriting that will cause no end of problems so we must check that this is not the case first.
if( typeof( myReference.innerHTML ) != 'undefined' ) {
//used by all current browsers
myReference.innerHTML = 'some <b>new</b> content';
} else if( myReference.document && myReference.document != window.document ) {
//used by layers browsers
myReference.document.open();
myReference.document.write('some <b>new</b> content');
myReference.document.close();
}
It is also possible to extend support to Opera 5 and 6 if needed, by providing an iframe (which should be given a name attribute), checking if it has loaded, then rewriting its contents:
if( typeof( myReference.innerHTML ) != 'undefined' ) {
//used by all current browsers
myReference.innerHTML = 'some <b>new</b> content';
} else if( myReference.document && myReference.document != window.document ) {
//used by layers browsers
myReference.document.open();
myReference.document.write('some <b>new</b> content');
myReference.document.close();
} else if( window.frames && window.frames.length && window.frames['nameOfIframe'] ) {
//used by browsers like Opera 6-
myReference = window.frames['nameOfIframe'].window;
myReference.document.open();
myReference.document.write('some <b>new</b> content');
myReference.document.close();
}
Test it here: rewrite the contents of the positioned element below (the Opera 5-6 workaround is not included).
This is the positioned element. The contents have not yet been rewritten.
Creating new positioned elements
- Opera 6- and OmniWeb 4.2-, NetFront 3.2- and Clue browser cannot create positioned elements once the page has loaded.
- WebTV will replace the entire content of the parent element as it incorrecty always reads innerHTML as a blank string.
- iCab 2- cannot position the element and should create them as unpositioned elements.
This functionality has been completely replaced in the W3C DOM, using createElement. The old DHTML approach should not be used in any new Web pages, and is best removed and replaced with DOM functionality. It is retained here to allow it to be recognised.
As the page is loading, we can create new positioned elements using document.write, or just regular HTML. Once the page has loaded, 5th generation browsers allow us to create any new elements, but some 4th generation browsers also allow us to create elements after the page has loaded.
Most browsers allow the innerHTML property of an element to be manipulated (the Internet Explorer series also provide insertAdjacentHTML, but most other DOM browsers do not include it). Layers browsers (with the exception of Omniweb 4.2-) provide a constructor that creates new empty layers, whose contents can then be written. Before trying to use this constructor, we must check it exists. Although OmniWeb 4.2- provides the Layer constructor, using it causes errors, so I use document.classes to isolate OmniWeb 4.2- and protect it from the script.
With the layers syntax, the new layer is entered into the layers collections using its numerical index but is not entered into the collection with a name, so we can add it there ourselves if we want to. We also have to specify a nominal maximum width. It will be positioned differently in different layers browsers, so we have to position it exactly ourselves. It will be hidden, so we must show it. With the innerHTML syntax, we can create ANY new content, but to be cross browser, I will create a positioned element.
Opera 7-7.1 incorrectly strips all existing tags in the parent element of their style attributes when reading innerHTML, producing an odd effect. To combat this, I use insertAdjacentHTML if the browser provides it, as this does not produce problems.
This first example will create a new positioned element as a child of the document.
if( document.layers && window.Layer && document.classes ) {
//create a layer 350px wide
document.layers['newName'] = new Layer( 350 );
//write its content
document.layers['newName'].document.open();
document.layers['newName'].document.write('new content');
document.layers['newName'].document.close();
//style it
document.layers['newName'].left = 0;
document.layers['newName'].top = 0;
document.layers['newName'].visibility = 'show';
} else if( document.body ) {
var theString = '<div style="position:absolute;left:0px;top:0px;' +
'width:350px;">new content</div>';
if( document.body.insertAdjacentHTML ) {
document.body.insertAdjacentHTML( 'beforeEnd', theString );
} else if( typeof( document.body.innerHTML ) != 'undefined' ) {
document.body.innerHTML += theString;
} else {
//FAILURE, nothing works
}
} else {
//FAILURE, nothing works
}
Th next example will create a new positioned element as a child of an existing positioned element (myReference is obtained as above):
if( document.layers && window.Layer && document.classes ) {
//create a layer 350px wide
document.layers['newName'] = new Layer( 350, myReference );
//write its content
document.layers['newName'].document.open();
document.layers['newName'].document.write('new content');
document.layers['newName'].document.close();
//style it
document.layers['newName'].left = 0;
document.layers['newName'].top = 0;
document.layers['newName'].visibility = 'show';
} else {
var theString = '<div style="position:absolute;left:0px;top:0px;' +
'width:350px;">new content</div>';
if( myReference.insertAdjacentHTML ) {
myReference.insertAdjacentHTML( 'beforeEnd', theString );
} else if( typeof( myReference.innerHTML ) != 'undefined' ) {
myReference.innerHTML += theString;
} else {
//FAILURE, nothing works
}
}
Test it here: create a new element (new elements will alternate in colour and will be slightly offset from each other to make it more easy to see what is happening).
This is the original content of the existing positioned element. It will not be changed.
Changing the background colour of the whole document
- Opera 5, OmniWeb 4.2- and Escape/Evo cannot change the background colour of the document (Escape will change the background colour, but only at the very end of the document, after all of the content).
- Opera 6 and Clue browser will only change the colour behind the content, the original background colour will remain where the content is smaller than the window.
- NetFront 3.3- will allow you to set the colour to '', but will not show any change until you scroll.
There are three ways to change the background colour. Old browsers use the bgColor property to style the background of the entire document. In current browsers, the HTML element and the BODY element are rendered separately, by default with the HTML element taking up just a few pixels outside the BODY. They are able to be styled separately, so to change the document background, both of them need to be changed. The HTML element is referenced in these browsers as document.documentElement, and the BODY is referenced as document.body.
Setting the wrong one will not cause errors (as long as they exist), so I set all of them at the same time.
if( document.documentElement && document.documentElement.style ) {
document.documentElement.style.backgroundColor = 'red'; }
if( document.body && document.body.style ) {
document.body.style.backgroundColor = 'red'; }
document.bgColor = 'red';
Test it here: change the background colour of this document to:
- #f6f6f6
- #d2cbff
- #777777
- '' (returns to default) - not allowed by some old browsers
Changing the display style of any element
- WebTV does not support the display style.
- Older browsers such as Netscape 4, Escape 4, Opera 6-, OmniWeb 4.2-, NetFront 3.2- and Clue browser support the display: none; style, but do not allow JavaScript to change it. See the guidelines below.
- iCab 2- sometimes makes mistakes with rendering when changing the display style and interprets 'block' as 'return to default'.
- Many device browsers will ignore the display style when in small screen reformatting mode.
- Internet Explorer 4 on Windows does not understand inline display.
- Escape 4 does actually allow you to change the display style (only block, inline and none accepted) using the style object, but only on layers and ilayers. Since the best use of the display style is for unpositioned elements, and considering that changing from none to inline or block has no effect in Escape until the window is resized, i do not recommend even attempting it.
All current browsers support the display style, and can be told to display any element like an inline element
(display:inline;
), like a block element (display:block;
), or not to display it at all(display:none;
).
Most also support many other display styles. However, some older browsers do not allow the display style to be changed with JavaScript,
so if the display style is initially set to 'none' and then you attempt to set it to 'block' or '', the display style will
not actually change, and the content will remain invisible. This is also the case for browsers where JavaScript is disabled.
For this reason, it is best to change the display style with script after the page has loaded. Browsers that do not understand it will just ignore you, and allow the user to view the content. It may not be as neat as being able to show and hide it, but at least they will be able to see it.
The display style is different from the visibility style. Setting the visibility style to 'hidden' will hide the element from view, but will leave the space for it. Setting the display style to 'none' will remove it from view and will re-arrange the contents of the page to fill the hole. This can make the feature very useful for menu systems, as with very simple programming, the browser can take care of all the re-arranging to make the page look nice again.
Browsers that allow elements to have their display style changed will all use document.getElementById or document.all, not document.layers. This makes life slightly easier. Of course, it is nice to be able to tell users that this will not work in their browser, so we will want to detect if the browser allows us to change the display style first. To do this, we must initially set the display style using inline style sheets, with it set the the element's default display ('inline' for elements like spans, and 'block' for elements such as paragraphs or DIV).
The HTML
In this example, I will have a span inside a paragraph:
<p>This is a paragraph.
<span style="display:inline;" id="aUniqueId">This is a span
within the paragraph whose display style has been set to
'inline' using an inline style sheet.</span> This is another
sentence in the paragraph, but not in the span.<p>
The JavaScript
function changeDisplay( elementId, setTo ) {
var theElement;
if( document.getElementById ) {
//DOM
theElement = document.getElementById( elementId );
} else if( document.all ) {
//Proprietary DOM
theElement = document.all[ elementId ];
}
if( !theElement ) {
/* The page has not loaded, or the browser claims to
support document.getElementById or document.all but
cannot actually use either */
return;
}
//Reference the style ...
if( theElement.style ) { theElement = theElement.style; }
if( typeof( theElement.display ) == 'undefined' ) {
//The browser does not allow us to change the display style
//Alert something sensible (not what I have here ...)
window.alert( 'Your browser does not support this' );
return;
}
//Change the display style
theElement.display = setTo;
}
Try it here: select a display style for the span in the paragraph below:
This is a paragraph. This is a span within the paragraph whose display style has been set to 'inline' using an inline style sheet. This is another sentence in the paragraph, but not in the span.
Last modified: 19 March 2011