Cross-browser (IE8-) getComputedStyle with Javascript?
Solution 1
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;
};
}
Solution 2
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;
}
Solution 3
instead of :
getComputedStyle !== 'undefined'
it should be :
typeof getComputedStyle !== 'undefined'
otherwise it would never works.
Solution 4
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);
};
}();
Solution 5
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
}
Related videos on Youtube
user1643156
Updated on May 19, 2020Comments
-
user1643156 almost 4 years
Since IE8 does not support
getComputedStyle
, we can only usecurrentStyle
. 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?
-
Pointy about 11 yearsThe IE
currentStyle
object shows you the browser default values for those properties. Perhaps you could use a CSS reset to normalize the defaults across all browsers. -
user1643156 about 11 years@Pointy I'm looking for a Javascript solution since I'm writing a small library which I don't want it to alter users' styles.
-
Mr_Green about 11 yearsThis link might help you.
-
user1643156 about 11 years@Mr_Green thanks but it doesn't help. I'v seen that page before. The code cannot parse values such as
medium
andauto
topx
.
-
-
Beejor almost 9 yearsIn case anyone else is wondering,
rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" );
. The full standalone source can be found here: stackoverflow.com/questions/17884653 -
Emile Bergeron over 7 yearsThis will fail for a prop like
backgroundColor
becausegetPropertyValue
expects the CSS property name, but thecurrentStyle
has it as the camel-case version. A one-liner replacement:return (typeof getComputedStyle !== 'undefined' ? getComputedStyle(el, null) : el.currentStyle)[prop];
-
blissfool almost 7 yearsThis doesn't answer the question though. You've merely fixed another answer which also doesn't answer the question.
-
blissfool almost 7 yearsThis doesn't answer the question. Question asks for cross-browser solution for "all properties", even the ones mentioned in the question where "currentStyle" doesn't return the real computed values.
-
Emile Bergeron almost 7 years@blissfool it does answer the part about a cross-browser equivalent for
getComputedStyle
which myself and a lot of other people seem to be looking for (based on upvotes). While you have the right to not like my answer, it was too big for an edit and it could help someone who comes across this question in the future, so I don't think it deserves a downvote. -
blissfool almost 7 yearsTechnically, the question was not asking about "cross-browser equivalent for getComputedStyle". Well, it was, but it was asked in a way that it should also return the correct values all the time. The question wasn't phrase too clearly at the end but that was the context. They already knew they needed to use getComputedStyle or currentStyle.
-
blissfool almost 7 yearsI do agree that it could be helpful for people who happens upon this question and was going to change my vote but it seems to be locked due to the amount of time that passed. I will change my vote if you want to make any slight edit.
-
Emile Bergeron almost 7 years@blissfool I added a disclaimer to explain why this answer exist. This should let you adjust the vote if you still want.