One of the more useful methods found in Mozilla browsers is the getComputedStyle method. This method, when called on an element, can return the computed runtime value of a specified style property using the getPropertyValue method.
While each Mozilla browser has its own quirks, the basic implementations are similiar. For example, if for an element you call getComputedStyle with the intent to find its width; it will return a length in pixels regardless of whether or not the style property was specified in pixels or at all on the element. As you may tell, this information is most useful for javascript functions that need to know the size of elements as they actually are on the screen.
Unfortunately Microsoft did not put this method into Internet Explorer 7 and below. This has left developers with the task of finding workarounds to their problems that would otherwise be easily solved had they the method. Fortunately, I may have found a satisfactory solution to IE's lacking support. - At least, for retrieving dimension sizes on block elements...
The following javascript object can return, in pixels ( or as possibly auto ), the computed width, height, padding, border width and more for block elements. The object relies on a code snippet I used in my width and height getter functions post about a month ago. The snippet is fairly straightforward, in which styleEl is the element we're looking at:
The argument "length" can be any sort of style value length such as 50px, 50em, 50pt, 50%, auto, etc. It will create a temporary DIV that will be placed in the same parent container as the element being called upon. This way relativity is maintained. The width is extracted and viola! - we have what we need.
One question you may be asking yourself is: why set the width every time and not the height? This is because even vertically-oriented styles such as margin-top, padding-top and border-top-width are based off of the horizontal. If you have a browser screen resolution of 800 x 600 and for an element, with parent element BODY with margin 0px, said that you wanted the padding-top to be 10%, it would be drawn 80px deep and not 60px. ( note: this does NOT apply to the height style )
Posted below is the full source code for the IE_computedStyle object. Please see the script's comments for usage. A demo is also available. ( please note that it was made for IE only and will return undefined purposefully in other browsers )
/////////////////////////////////////////////////////////////////
// JS Object: IE_computedStyle
// Returns the computed style, expressed in pixels or as auto, for the given element
//
// Usage:
// IE_computedStyle.get(elementNode, CSS-Style);
//
// Examples:
// IE_computedStyle.get(el, "width");
// IE_computedStyle.get(el, "margin-top");
/////////////////////////////////////////////////////////////////
var IE_computedStyle = function () {
var isIE = /*@cc_on!@*/0;
var borderRegex = /thin|medium|thick/i; /* Regex for css border width keywords */
var styleEl;
/* GET POS */
var getPos = function (which) {
var curStyle = styleEl.currentStyle[which];
return (/auto/i.test(curStyle)) ? "auto" : grabLength(curStyle) + "px";
};
/* GET MARGIN */
var getMargin = function (which) {
var curStyle = styleEl.currentStyle["margin" + which];
return (/auto/i.test(curStyle)) ? "0px" : grabLength(curStyle) + "px";
};
/* GET BORDER WIDTH */
var getBorderWidth = function (which) {
var borderWidth = styleEl.currentStyle["border" + which + "Width"];
if (styleEl.currentStyle["border" + which + "Style"] !== "none" &&
((/Top|Bottom/i.test(which) && styleEl.offsetHeight > styleEl.clientHeight) ||
(/Right|Left/i.test(which) && styleEl.offsetWidth > styleEl.clientWidth))) {
if (!borderRegex.test(borderWidth)) {
return grabLength(borderWidth) + "px";
} else if (borderRegex.test(borderWidth)) {
var temp = document.createElement("DIV");
temp.style.width = "10px";
temp.style.border = borderWidth + " " + styleEl.currentStyle["border" + which + "Style"] + " #000000";
styleEl.parentNode.appendChild(temp);
borderWidth = Math.round((temp.offsetWidth-10)/2);
styleEl.parentNode.removeChild(temp);
return borderWidth + "px";
}
} else {
return "0px";
}
};
/* GET PADDING */
var getPadding = function (which) {
return grabLength(styleEl.currentStyle["padding" + which]) + "px";
};
/* GET WIDTH */
var getWidth = function () {
var width = styleEl.offsetWidth; /* Currently the width including padding + border */
width -= parseInt(getPadding("Right"));
width -= parseInt(getPadding("Left"));
width -= parseInt(getBorderWidth("Right"));
width -= parseInt(getBorderWidth("Left"));
return width + "px";
};
/* GET HEIGHT */
var getHeight = function () {
var height = styleEl.offsetHeight; /* Currently the height including padding + border */
height -= parseInt(getPadding("Top"));
height -= parseInt(getPadding("Bottom"));
height -= parseInt(getBorderWidth("Top"));
height -= parseInt(getBorderWidth("Bottom"));
return height + "px";
};
/* GRAB LENGTH */
var grabLength = function (length) {
var temp = document.createElement("DIV");
temp.style.width = length;
styleEl.parentNode.appendChild(temp);
length = Math.round(temp.offsetWidth);
styleEl.parentNode.removeChild(temp);
return length;
};
return {
/* GET */
get : function (el, styleProp) {
var rValue;
styleEl = (typeof(el) === "string") ? document.getElementById(el) : el;
var styleProp = (typeof(styleProp) === "string") ? styleProp.toLowerCase() : "";
styleProp = styleProp.replace(/\-/g, "");
if (!isIE || !/block/i.test(styleEl.currentStyle["display"]))
return;
switch (styleProp) { /* Run through the valid css properties, return undefined if none match */
case "top": rValue = getPos("top"); break;
case "right": rValue = getPos("right"); break;
case "bottom": rValue = getPos("bottom"); break;
case "left": rValue = getPos("left"); break;
case "margintop": rValue = getMargin("Top"); break;
case "marginright": rValue = getMargin("Right"); break;
case "marginbottom": rValue = getMargin("Bottom"); break;
case "marginleft": rValue = getMargin("Left"); break;
case "bordertopwidth": rValue = getBorderWidth("Top"); break;
case "borderrightwidth": rValue = getBorderWidth("Right"); break;
case "borderbottomwidth": rValue = getBorderWidth("Bottom"); break;
case "borderleftwidth": rValue = getBorderWidth("Left"); break;
case "paddingtop": rValue = getPadding("Top"); break;
case "paddingright": rValue = getPadding("Right"); break;
case "paddingbottom": rValue = getPadding("Bottom"); break;
case "paddingleft": rValue = getPadding("Left"); break;
case "width": rValue = getWidth(); break;
case "height": rValue = getHeight(); break;
}
return rValue;
}
};
}();
As always, if you run into any issues please post away. Thanks!
Comments