faqts : Computers : Programming : Languages : JavaScript : DHTML

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

113 of 122 people (93%) answered Yes
Recently 10 of 10 people (100%) answered Yes

Entry

How to retrieve computed CSS property values with Javascript in IE4 , NN4 , NN6

Dec 29th, 2000 21:44
Ian Grant,


If you're like me, you've been frustrated while porting your DHTML 
scripts to the new W3C DOM.  Unless you're familliar with deciphering 
W3C's DOM documents, you are probably running into challenges.  I've 
spent some time researching the new DOM (especially NN6's 
implementation), its capabilities and its incapabilities.  Here is 
something I haven't seen posted yet in these FAQts that I thought might 
be useful.
    Both Internet Explorer and Netscape Navigator (fourth generation or 
better) provide simple facilities for retrieving the browser's 
calculated CSS property values.  For example:
To retrieve an element's computed width and height in IE4+:
----------------------------------------------------------
    objWidth = document.all.myDiv.offsetWidth;
    objHeight = document.all.myDiv.offsetHeight;
(Note that in IE, 'document.all.' isn't required.  Besides, why keep 
troubling the browser with repeatedly querying the DOM?  8^)
And in NN4+:
-----------
    objWidth = document.layers.myDiv.clip.width;
    objHeight = document.layers.myDiv.clip.height;
Doing this in the new W3C DOM (NN6/Mozilla) requires a bit more code:
--------------------------------------------------------------------
    docObj = document.getElementById("myDiv");
    objHeight = document.defaultView.getComputedStyle
(docObj, "").getPropertyValue("height");
    objWidth = document.defaultView.getComputedStyle
(docObj, "").getPropertyValue("width");
This also translates well to finding the calculated "top" and "left" 
values of both relative and absolute positioned elements.
In IE4+:
-------
    objTop = document.all.myDiv.offsetTop;
    objLeft = document.all.myDiv.offsetLeft;
And NN4+:
--------
    objTop = document.layers.myDiv.pageY;
    objLeft = document.layers.myDiv.pageX;
And in NN6:
----------
    docObj = document.getElementById("myDiv");
    objTop = document.defaultView.getComputedStyle
(docObj, "").getPropertyValue("top");
    objLeft = document.defaultView.getComputedStyle
(docObj, "").getPropertyValue("left");
I have written the following code to demonstrate retrieving these 
properties and some other 'calculated' property values:
------------------------------------------------------------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Retrieving Computed CSS Properties</title>
<style>
<!--
div { position:absolute; top:50; left:100; };
-->
</style>
</head>
<body onLoad="start()">
<div id="myDiv" style="clip: rect(4px 200px 12px 36px); visibility: 
visible; z-index: 5">What are myDiv's CSS properties?</div>
<script language="javascript">
<!--
isNS4 = (document.layers) ? 1 : 0;
isIE4 = (document.all) ? 1 : 0;
isW3C = (document.getElementById && !document.all) ? 1 : 0;
function getCalculatedProperty(objName, property) {
    // ***** W3C Compatible DOM (NN6, Mozilla 16, etc.) *****
    if (isW3C) {
        docObj = document.getElementById(objName);
        if (property == "visibility") {
	    cssp = docObj.style.visibility;
	    return (cssp == "") ? "inherit" : cssp;
	}
	if (property == "clip") {
	    cssp = docObj.style.clip;
	    if (cssp == "") {
		cssStr = "rect(0px "; 
		cssStr += getCalculatedProperty(objName, "width") + " ";
		cssStr += getCalculatedProperty(objName, "height") 
+ " ";
		cssStr += "0px)";
		return cssStr;
	    }
	    return cssp;
	}
	if (property == "zIndex") {
	    cssp = docObj.style.zIndex;
	    return (cssp == "") ? "inherit" : cssp;
	}
	cssp = document.defaultView.getComputedStyle
(docObj, "").getPropertyValue(property);
	return (cssp == "") ? "unknown" : cssp;
    }
    // ***** Netscape Navigator 4+ DOM *****
    if (isNS4) {
	docObj = document.layers[objName];
	if (property == "visibility") {
	    cssp = docObj.visibility;
	    return (cssp == "hide") ? "hidden" : (cssp 
== "show") ? "visible" : "inherit";
	}
	if (property == "clip") {
	    cssStr = "rect(" + docObj.clip.top + "px ";
	    cssStr += docObj.clip.right + "px ";
	    cssStr += docObj.clip.bottom + "px ";
	    cssStr += docObj.clip.left + "px)";
	    return cssStr;
	}
	if ((property == "width") || (property == "height")) {
	    return eval("docObj.clip." + property) + "px";
	}
	if (property == "top") property = "pageY";
	if (property == "left") property = "pageX";
	cssp = eval("docObj." + property);
	if (property != "zIndex") cssp += "px";
	return cssp;
    }
    // ***** Internet Explorer 4+ DOM *****
    if (isIE4) {
	if (property == "width") return eval(objName + ".offsetWidth") 
+ "px";
	if (property == "height") return eval(objName 
+ ".offsetHeight") + "px";
	if (property == "clip") {
	    cssp = eval(objName + ".style.clip");
	    if (cssp == "") {
		cssStr = "rect(0px ";
		cssStr += getCalculatedProperty(objName, "width") + " ";
		cssStr += getCalculatedProperty(objName, "height") 
+ " ";
		cssStr += "0px)";
		return cssStr;
	    }
	    return cssp;
	}
	if (property == "top") return eval(objName + ".offsetTop") 
+ 'px';
	if (property == "left") return eval(objName + ".offsetLeft") 
+ 'px';
        // Else, use 'currentStyle' to find the rest
	return eval(objName + ".currentStyle." + property);
    }
}
function start() { 
    str = "Browser: ";
    str += (isIE4) ? "Internet Explorer 4+" : (isNS4) ? "Netscape 
Navigator 4+" : (isW3C) ? "W3C Compliant" : "unknown";
    str += "\nmyDiv.height = " + getCalculatedProperty
("myDiv", "height") + "\n";
    str += "myDiv.width = " + getCalculatedProperty("myDiv", "width") 
+ "\n";
    str += "myDiv.top = " + getCalculatedProperty("myDiv", "top") 
+ "\n";
    str += "myDiv.left = " + getCalculatedProperty("myDiv", "left") 
+ "\n";
    str += "myDiv.clip = " + getCalculatedProperty("myDiv", "clip") 
+ "\n";
    str += "myDiv.visibility = " + getCalculatedProperty
("myDiv", "visibility") + "\n";
    str += "myDiv.zIndex = " + getCalculatedProperty("myDiv", "zIndex");
    alert(str);
}
//-->
</script>
</body>
</html>
------------------------------------------------------------------------
    Note that there is plenty of room for optimization in my code.  It 
was written this way for clarity rather than efficiency.  Also note 
that even though NN6 inherits the 'visibility' and 'z-index' properties 
from an embedded stylesheet, it returns a null string when read 
(replaced by 'inherit' in my code).  A possible work-around would be to 
place these CSS properties inline as I did in the <div> above.  (If 
anybody knows of a way to retrieve these 'inherited' property values 
without parsing stylesheets or HTML documents, please let me know. 8^)
    As usual, NN4 requires that the body of the document finish loading 
before all of its elements ('myDiv') can have their properties read (or 
an error will occur).  Much in the same fashion, NN6 produces undefined 
results if a value is retrieved before the body finishes loading.  For 
example, if you were to read the calculated width of 'myDiv' before the 
page finished loading, you might get the width of the browser window 
instead.
Cheers!
Ian.
IDGrant@myBC.com