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