Since IE8 does not support getComputedStyle
, we can only use currentStyle
. However, it does not return the real "computed" value for some properties.
For example:
<style type="text/css">
#div {/* no properties are defined here */}
</style>
<div id="div">div</div>
// returns "medium" instead of 0px
document.getElementById('div').currentStyle.borderLeftWidth
// returns "auto" instead of 0px
document.getElementById('div').currentStyle.marginLeft
// returns "undefined" instead of 1
document.getElementById('div').currentStyle.opacity
Does anyone have a cross-browser solution for all properties without using jQuery or other Javascript libraries?
You don't want to use jquery but there's nothing preventing you from peeking into the code and see how they dealt with it :-)
Inside jquery code there's a reference about this comment which seems to the point (read also the whole article).
Here's the jquery code that should deal with your problem:
else if ( document.documentElement.currentStyle ) {
curCSS = function( elem, name ) {
var left, rsLeft,
ret = elem.currentStyle && elem.currentStyle[ name ],
style = elem.style;
// Avoid setting ret to empty string here
// so we don't default to auto
if ( ret == null && style && style[ name ] ) {
ret = style[ name ];
}
// From the awesome hack by Dean Edwards
// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
// If we're not dealing with a regular pixel number
// but a number that has a weird ending, we need to convert it to pixels
// but not position css attributes, as those are proportional to the parent element instead
// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
// Remember the original values
left = style.left;
rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
// Put in the new values to get a computed value out
if ( rsLeft ) {
elem.runtimeStyle.left = elem.currentStyle.left;
}
style.left = name === "fontSize" ? "1em" : ret;
ret = style.pixelLeft + "px";
// Revert the changed values
style.left = left;
if ( rsLeft ) {
elem.runtimeStyle.left = rsLeft;
}
}
return ret === "" ? "auto" : ret;
};
}
Here's a cross-browser function to get a computed style...
getStyle = function (el, prop) {
if (typeof getComputedStyle !== 'undefined') {
return getComputedStyle(el, null).getPropertyValue(prop);
} else {
return el.currentStyle[prop];
}
}
You may store it as an utility within an object, or just use it as provided. Here's a sample demo!
// Create paragraph element and append some text to it
var p = document.createElement('p');
p.appendChild(document.createTextNode('something for fun'));
// Append element to the body
document.getElementsByTagName('body')[0].appendChild(p);
// Set hex color to this element
p.style.color = '#999';
// alert element's color using getStyle function
alert(getStyle(p, 'color'));
Check this demo to see it in action:
getStyle = function(el, prop) {
if (getComputedStyle !== 'undefined') {
return getComputedStyle(el, null).getPropertyValue(prop);
} else {
return el.currentStyle[prop];
}
}
// Create paragraph element and append some text to it
var p = document.createElement('p');
p.appendChild(document.createTextNode('something for fun'));
// Append element to the body
document.getElementsByTagName('body')[0].appendChild(p);
// Set hex color to this element
p.style.color = '#999';
// alert element's color using getStyle function
console.log(getStyle(p, 'color'));
p {
color: red;
}
instead of :
getComputedStyle !== 'undefined'
it should be :
typeof getComputedStyle !== 'undefined'
otherwise it would never works.
This will not work for all styles but will work for dimensions (which is what I needed).
Instead of trying to guess what styles are applied, simply use the position in pixels of each of the four sides of a box-like element to calculate the dimensions. This will also work back to IE 5 and FF 3.
height = elem.getBoundingClientRect().bottom - elem.getBoundingClientRect().top;
width = elem.getBoundingClientRect().right - elem.getBoundingClientRect().left;
See also: getBoundingClientRect is awesome
If this still doesn't work for you, check out this fiddle I put together for calculating the inside width of a box. It uses the following as a shim for getComputedStyle:
/**
* getComputedStyle function for IE8
* borrowed from:
* http://missouristate.info/scripts/2013/common.js
*/
"getComputedStyle" in window || function() {
function c(a, b, g, e) {
var h = b[g];
b = parseFloat(h);
h = h.split(/\d/)[0];
e = null !== e ? e : /%|em/.test(h) && a.parentElement ? c(a.parentElement, a.parentElement.currentStyle, "fontSize", null) : 16;
a = "fontSize" == g ? e : /width/i.test(g) ? a.clientWidth : a.clientHeight;
return "em" == h ? b * e : "in" == h ? 96 * b : "pt" == h ? 96 * b / 72 : "%" == h ? b / 100 * a : b;
}
function a(a, c) {
var b = "border" == c ? "Width" : "", e = c + "Top" + b, h = c + "Right" + b, l = c + "Bottom" + b, b = c + "Left" + b;
a[c] = (a[e] == a[h] == a[l] == a[b] ? [a[e]] : a[e] == a[l] && a[b] == a[h] ? [a[e], a[h]] : a[b] == a[h] ? [a[e], a[h], a[l]] : [a[e], a[h], a[l], a[b]]).join(" ");
}
function b(b) {
var d, g = b.currentStyle, e = c(b, g, "fontSize", null);
for (d in g) {
/width|height|margin.|padding.|border.+W/.test(d) && "auto" !== this[d] ? this[d] = c(b, g, d, e) + "px" : "styleFloat" === d ? this["float"] = g[d] : this[d] = g[d];
}
a(this, "margin");
a(this, "padding");
a(this, "border");
this.fontSize = e + "px";
return this;
}
b.prototype = {};
window.getComputedStyle = function(a) {
return new b(a);
};
}();
This was too big for an edit, so it was made an answer but it doesn't provide a full answer to the question at hand.
Gabriel's answer fails with a property like "backgroundColor"
or "background-color"
depending on the browser version because .getPropertyValue
expects the CSS property name and el.currentStyle[prop]
needs the camel-case version.
Here's a fixed version which always expects the camel-case version:
function getStyle(el, prop) {
return (typeof getComputedStyle !== 'undefined' ?
getComputedStyle(el, null) :
el.currentStyle
)[prop]; // avoid getPropertyValue altogether
}