get computed width in pixels in Opera
Asked Answered
R

4

6

How can I get the computed width of an element in Opera? In other browsers I can do this:

// getComputedStyle wrapper
function getStyle(element, styleProp) {
  return element.currentStyle ? element.currentStyle[styleProp] :
      getComputedStyle(element, null).getPropertyValue(styleProp);
}

...but this only sort of works on Opera. It returns "auto" for a lot of things instead of a useful pixel value.

Here's a live demo that expands some text to fit in a box. It doesn't work on Opera, because the computed width is auto instead of a px value as in other browsers.

live demo in different browsers

How can I get more useful computed styles, such as the pixel width of an element, in Opera?

I realize that I can, in this case, use offsetWidth instead of getting the computed style. I appreciate the advice, but the real point of this question is that I want to know how to get computed styles in Opera where the style is actually computed in units. I don't care about offsetWidth for the purposes of this question.

Rosie answered 7/2, 2012 at 8:25 Comment(1)
Why dont you use any framework for detecting width and height in different browsers? jQuery made this routine easily and elegantly. Just use $(glyph).width() insteed getStyle(glyph, 'width') jsbin.com/ikatuc/2/edit#javascript,html,live Tested in Opera 10.63, IE6-8, Chrome, FirefoxExtravehicular
S
2

It also fails in IE <= 8

The reason is because currentStyle and getComputedStyle work differently in this case. If you were testing for getComputedStyle first it would work in both Opera and IE 9-10. Opera tries to mimic IE in a lot of cases (see innerText vs textContent), so it has currentStyle too.

BUT please note that you lose your "expected" behavior if the element in question has display:inline in it's style (FF, Chrome, IE), because they will report "auto" for you... except... you guessed it, in Opera which will then show you the "correct" px width of the element.

If you want a general purpose function you better off including a general purpose library (which as you will find are filled with edge cases you will never need). If you have a specific purpose to solve you can use a compatible replacement.

Computed style isn't really useful for you in this case. What you need is probably clientWidth, offsetWidth or scrollWidth depending on your needs. They differ mainly in whether you want to include padding, border, margin and/or clipped areas (in case of horizontally overflowing content).

They are supported even on ancient browsers like IE 6, in fact these properties were first introduced by MS back in the first browser war (just like innerHTML).

You can read more about them by googling with MSDN or MDN.

Sarcomatosis answered 15/2, 2012 at 15:42 Comment(8)
Computed style is useful to me in every other browser besides Opera. This question is about how to get a useful computed style in Opera, not how to work around it with clientWidth. Would it help if I changed the example to get the font color or something?Rosie
Alright, I just answered your question (as per your title and original description). If you have a specific problem why do you ask something else? I'm not sure if you try to solve a problem or just want to create one...Sarcomatosis
I have a specific question. My original post ended with "How can I get more useful computed styles, such as the pixel width of an element, in Opera?" This is a summary of my question. Nothing has changed. I want to get computed styles, not offsetWidth.Rosie
Anyway, did you really think I'd go for this answer, seeing as hallvors already mentioned offsetWidth and I didn't mark it correct? I wanted more clarification on Opera's behavior, and suggestions to get it to behave as I wanted, not a rehashing of a previous answer.Rosie
No I don't care about points, I only care about people who have a problem to solve. I don't care if you accept my answer, the other one was just not complete (because offsetWidth may not be the correct answer depending on the use-case). But then again I might've been foolish to think that there ever was a use-case...Sarcomatosis
Of course there is a use case. The use case is the getStyle function, displayed right at the top of the post. It acts the same in every browser but Opera. I want it to act the same in Opera as it does in other browsers. Nothing about this is ambiguous.Rosie
No, because you're not using that function, it's only a definition. If you want a general purpose function you better off including a general purpose library (which as you will find are filled with edge cases you will never need). If you have a specific purpose to solve you can use a compatible replacement.Sarcomatosis
Checking getComputedStyle first works like a charm. Thank you.Rosie
G
5

What CSS calls "computed value" isn't always what you expect. I guess Opera follows the spec to the T here while the other browsers do something they consider more useful.

I'd suggest using element.offsetWidth instead of getComputedStyle() for this purpose.

Ganef answered 7/2, 2012 at 9:19 Comment(8)
Hmm, I wanted to use real DOM methods, but maybe it does make more sense to go with non-standard offsetWidth here. Could you provide a link to the relevant section of the spec that you are saying Opera follows to a T? I'm surprised they're the only ones who have done it this way if it's really the specified behavior.Rosie
Caveat: I'm not a CSS guru. However, my understanding of this is that there is a distinction in CSS (see w3.org/TR/CSS2/cascade.html for definitions) between "computed" and "actual" values, where "computed" may not always actually be a pixel value. Now, this may not be spec'ed in sufficient detail to let me precisely claim that Opera does it "right" - let's say we do what we thought was exactly right at the time it was implemented but other browsers seem to be shipping other decisions.. ;)Ganef
I see that developer.mozilla.org/en/CSS/computed_value states: "The getComputedStyle DOM API returns the used value, not the computed value.". Well, that explains it :-pGanef
Oh man, that's confusing. The spec says getComputedStyle method provides a read only access to the computed values of an element but doesn't mention "used values" anywhere. Now I'm curious how the other browsers justify their behavior.Rosie
But wait, it says here "Relative values, on the other hand, must be transformed into computed values ... 'auto' values must be computed" ... doesn't that sound like these "auto" values opera is giving should be converted to units?Rosie
FYI: used values were introduced in CSS 2.1, and are equivalent to CSS 2.0 computed values. The term computed values means something different in CSS 2.1. See: developer.mozilla.org/en/DOM/window.getComputedStyle#NotesSarcomatosis
Aha. The way the definitions have been shifted around is really confusing :-o but it sounds like it is a bug in Opera, and that despite the name, the method should actually return the used values as defined in CSS 2.1 ..Ganef
@Ganef actually I think Opera does do this, so it's not a bug... apparently Opera emulates IE's currentStyle, which I wasn't aware of (see galambalazs' answer). The 'auto' result was coming from currentStyle; getComputedStyle returns the result I expected. None of which makes things any less confusing. ;)Rosie
S
2

It also fails in IE <= 8

The reason is because currentStyle and getComputedStyle work differently in this case. If you were testing for getComputedStyle first it would work in both Opera and IE 9-10. Opera tries to mimic IE in a lot of cases (see innerText vs textContent), so it has currentStyle too.

BUT please note that you lose your "expected" behavior if the element in question has display:inline in it's style (FF, Chrome, IE), because they will report "auto" for you... except... you guessed it, in Opera which will then show you the "correct" px width of the element.

If you want a general purpose function you better off including a general purpose library (which as you will find are filled with edge cases you will never need). If you have a specific purpose to solve you can use a compatible replacement.

Computed style isn't really useful for you in this case. What you need is probably clientWidth, offsetWidth or scrollWidth depending on your needs. They differ mainly in whether you want to include padding, border, margin and/or clipped areas (in case of horizontally overflowing content).

They are supported even on ancient browsers like IE 6, in fact these properties were first introduced by MS back in the first browser war (just like innerHTML).

You can read more about them by googling with MSDN or MDN.

Sarcomatosis answered 15/2, 2012 at 15:42 Comment(8)
Computed style is useful to me in every other browser besides Opera. This question is about how to get a useful computed style in Opera, not how to work around it with clientWidth. Would it help if I changed the example to get the font color or something?Rosie
Alright, I just answered your question (as per your title and original description). If you have a specific problem why do you ask something else? I'm not sure if you try to solve a problem or just want to create one...Sarcomatosis
I have a specific question. My original post ended with "How can I get more useful computed styles, such as the pixel width of an element, in Opera?" This is a summary of my question. Nothing has changed. I want to get computed styles, not offsetWidth.Rosie
Anyway, did you really think I'd go for this answer, seeing as hallvors already mentioned offsetWidth and I didn't mark it correct? I wanted more clarification on Opera's behavior, and suggestions to get it to behave as I wanted, not a rehashing of a previous answer.Rosie
No I don't care about points, I only care about people who have a problem to solve. I don't care if you accept my answer, the other one was just not complete (because offsetWidth may not be the correct answer depending on the use-case). But then again I might've been foolish to think that there ever was a use-case...Sarcomatosis
Of course there is a use case. The use case is the getStyle function, displayed right at the top of the post. It acts the same in every browser but Opera. I want it to act the same in Opera as it does in other browsers. Nothing about this is ambiguous.Rosie
No, because you're not using that function, it's only a definition. If you want a general purpose function you better off including a general purpose library (which as you will find are filled with edge cases you will never need). If you have a specific purpose to solve you can use a compatible replacement.Sarcomatosis
Checking getComputedStyle first works like a charm. Thank you.Rosie
D
0

There shouldn't be any reason this has to be difficult if you keep your code well structured, never put script elements as children to the body element even if it validates as it will lead to very poor coding practices. On the other hand I commend you for using appendChild instead of the unreliable innerHTML so at least you're making an effort to not take the lazy route.

Use an anonymous function for the onload event so you can execute more than one function obviously. I'm not familiar with glyphs (SVG?) so I was not able to get any browser to render the glyph at anything other than 7px.

Here is the reworked code...

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>get computed width in pixels in Opera</title>
<script type="application/javascript">
//<![CDATA[

// getComputedStyle wrapper
function getStyle(element, styleProp)
{
 return element.currentStyle ? element.currentStyle[styleProp] : getComputedStyle(element, null).getPropertyValue(styleProp);
}

// cheesy convenience function
function textDiv(textContent, className)
{
 var tmp = document.createElement('div');
 if (className) tmp.className = className;
 tmp.appendChild(document.createTextNode(textContent));
 return tmp;
}

window.onload = function()
{
 var box = document.getElementById('box'),glyph = box.appendChild(textDiv('g', 'glyph')),size=500;

 glyph.style.position = 'absolute';
/*
 document.getElementById('status').appendChild(textDiv('Initial computed width: ' + getStyle(glyph, 'width')));

 while (parseInt(getStyle(glyph, 'width'), 10) <  100)
 {
  glyph.style.fontSize = size++ + '%';
 }
*/
 document.getElementById('status').appendChild(document.createTextNode(document.getElementById('box').firstChild.scrollWidth+'px'));
}

//]]>
</script>
</head>

<body>

<div id="status"></div>
<div id="box"></div>

</body>
</html>
Dismember answered 17/2, 2012 at 0:1 Comment(1)
jsbin must have put those script elements in there, I just typed them into the script panel. "Glyph" doesn't make much sense here; it made more sense in the code I copy-pasted this from. It just means "symbol" basically. In this case the symbol is a letter G.Rosie
T
0

You can use this code to get the property in Opera:

document.defaultView.getComputedStyle(element,null).getPropertyValue(styleProp);
Torch answered 17/2, 2012 at 15:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.