offsetLeft bug with borders in IE when width: is specified?

M

Matt Kruse

See: http://www.mattkruse.com/temp/offsetleft.html

It appears that the offsetLeft value in IE6 (other versions not tested)
incorrectly ignores the border width on a DIV when there is a width:
property specified. Without a specified width: it gets it correct.

Does anyone know
1) If this is a known bug, and if it affects any other browsers? I tested a
few and found no problems.

2) Is there a work-around for this to arrive at the correct value which will
not break other browsers which already get it right? Resorting to browser
sniffing is not my preference.


For discussion purposes, here is the content of the url above. Beware, lines
may wrap inappropriately.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<style type="text/css">
body { margin:0; }
</style>
</head>
<body>

<hr>
<B>In IE6, this reports "offsetLeft of span from BODY is: 35" which is
correct (10px border + 25px padding)</B>
<br>
<pre>
&lt;div style="border:10px solid black; padding:25px;
background-color:yellow;"&gt;
&lt;span id="span1"&gt;span&lt;/span&gt;
&lt;/div&gt;
</pre>
<div id="div1" style="border:10px solid black; padding:25px;
background-color:yellow;">
<span id="span1">span</span>
</div>
offsetLeft of span from
<script type="text/javascript">
document.write(document.getElementById('span1').offsetParent.nodeName)
</script>
is:
<script type="text/javascript">
document.write(document.getElementById('span1').offsetLeft)
</script>

<br>
<br>
<hr>

<B>In IE6, this reports "offsetLeft of span from DIV is: 25" which is
incorrect. The 10px border is ignored. The only difference is that this DIV
has a width specified.</B>
<br>

<pre>
&lt;div style="border:10px solid black; padding:25px;
background-color:yellow; width:200px;"&gt;
&lt;span id="span2"&gt;span&lt;/span&gt;
&lt;/div&gt;
</pre>
<div id="div2" style="border:10px solid black; padding:25px;
background-color:yellow; width:200px;">
<span id="span2">span</span>
</div>
offsetLeft of span from
<script type="text/javascript">
document.write(document.getElementById('span2').offsetParent.nodeName)
</script>
is:
<script type="text/javascript">
document.write(document.getElementById('span2').offsetLeft)
</script>

</body>
</html>
 
V

VK

Matt said:
See: http://www.mattkruse.com/temp/offsetleft.html

It appears that the offsetLeft value in IE6 (other versions not tested)
incorrectly ignores the border width on a DIV when there is a width:
property specified. Without a specified width: it gets it correct.

<http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/offsetheight.asp>

To comply with the Cascading Style Sheets, Level 1 (CSS1) box model,
Microsoft Internet Explorer 6 and later calculate the height of objects
differently when you use the !DOCTYPE declaration in your document to
switch on standards-compliant mode. This difference may affect the
value of the offsetHeight propety. When standards-compliant mode is
switched on, the height property specifies the distance between the top
and bottom edges of the bounding box that surrounds the object's
content. When standards-compliant mode is not switched on, and with
earlier versions of Internet Explorer, the height property also
includes the border and padding belts that surround the object's
bounding box. For more information, see CSS Enhancements in Internet
Explorer 6.
 
V

VK

Also must-have tables are located at:
<http://msdn.microsoft.com/library/en-us/dnie60/html/cssenhancements.asp>

As you may notice, Internet Explorer 6.x indeed respects DTD Strict if
properly declared. You may also already noticed (on your own
experience) that DTD Strict is something you would never want to use by
your own free will. ;-))

The discussion topic - if indeed other browsers behave as expected in
DTD Strict - could be then refrased to: "who is indeed acting by
standards and who is spitting on DTD?" (though it's actually in the CSS
domain).
 
R

Richard Cornford

Matt said:
See: http://www.mattkruse.com/temp/offsetleft.html

It appears that the offsetLeft value in IE6 (other
versions not tested) incorrectly ignores the border
width on a DIV when there is a width: property specified.
Without a specified width: it gets it correct.

Does anyone know
1) If this is a known bug, and if it affects any other
browsers? I tested a few and found no problems.

If you look at the offsetParents of the two spans you will see that the
first's is the BODY element and the second's is the DIV that is also its
parentNode. So the consequence of adding a CSS width property to the
second DIV is to alter its status in the hierarchy of offsets.

In both cases the offsetLeft property is reporting the distance to the
inside of the border of the respective offsetParent.

Add margins to the two DIVs and the offsetLeft vales will diverge by
more than could be accounted for with the border.
2) Is there a work-around for this to arrive at the
correct value which will not break other browsers which
already get it right?
<snip>

No workaround is necessary as there is nothing wrong here.

Richard.
 
M

Matt Kruse

Richard said:
If you look at the offsetParents of the two spans you will see that
the first's is the BODY element and the second's is the DIV that is
also its parentNode. So the consequence of adding a CSS width
property to the second DIV is to alter its status in the hierarchy of
offsets.

Correct. I don't know why this is the case, but it doesn't really matter. As
long as you walk up the offsetParent chain, you should arrive at the top
either way.
In both cases the offsetLeft property is reporting the distance to the
inside of the border of the respective offsetParent.

You are correct. However, walking up the offsetParent chain and summing the
offsetLeft values then results in the wrong value if there are any borders
along the way.
Add margins to the two DIVs and the offsetLeft vales will diverge by
more than could be accounted for with the border.

See the example again:
http://www.mattkruse.com/temp/offsetleft.html

The values seem fine with both padding and margins. It's only the borders
that get skipped.
No workaround is necessary as there is nothing wrong here.

There certainly is. When borders are applied to elements, there doesn't
appear to be a way in IE to easily compute the real offset of a given
object. You would need to manually consider the border sizes as you go up.
But how would you even detect through script that you would need to add the
borders, when other browsers handle it just fine without any tricks
required? And how can you even know the width of the border, when it might
be specified in units like inches or em's?
 
R

Richard Cornford

Matt said:
There certainly is. When borders are applied to elements,
there doesn't appear to be a way in IE to easily compute
the real offset of a given object.

It is easy on a browser that support - getComputedStyle -. Given that
last time we discussed the positioning problem you implied that I didn't
know what I was talking about I am inclined to leave you to sort this
out for yourself, but no, I will give you the clue -> clientTop/Left.
You would need to manually consider the border sizes
as you go up. But how would you even detect through
script that you would need to add the borders, when
other browsers handle it just fine without any tricks
required?

Have you verified that other browsers don't report offsetTop/Left from
inside the borders of the offsetParent?
And how can you even know the width of the border, when it
might be specified in units like inches or em's?

;-)

Richard.
 
M

Matt Kruse

Richard said:
Given that
last time we discussed the positioning problem you implied that I
didn't know what I was talking about I am inclined to leave you to
sort this out for yourself

Actually, I said I couldn't tell whether you knew what you were talking
about or not, because you refused to give any details.
but no, I will give you the clue -> clientTop/Left.

Indeed, that does help. However, it also has its problems.
For example:

<table cellspacing=0 cellpadding=0 border=10>
<tr>
<td style="padding:25px;border:15px solid black;"><span>Find
Me!</span></td>
</tr>
</table>

In IE6 which I am testing with, I get this:
SPAN's offsetParent is TD, offsetLeft = 25 (padding)... CORRECT
TD has clientLeft = 15 (border)... CORRECT

TD's offsetParent is TABLE, offsetLeft = 10 (border)... CORRECT???
TABLE's clientLeft = 10 (border)... CORRECT???

So the table's border gets counted both in the offsetLeft and in the
clientLeft.
If I add up all offsetLeft+clientLeft values, I get the wrong result.
In the case of TABLE (maybe others?) I need to ignore the clientLeft value.
 
V

VK

Matt said:
In IE6 which I am testing with, I get this:
SPAN's offsetParent is TD, offsetLeft = 25 (padding)... CORRECT
TD has clientLeft = 15 (border)... CORRECT

TD's offsetParent is TABLE, offsetLeft = 10 (border)... CORRECT???
TABLE's clientLeft = 10 (border)... CORRECT???

So the table's border gets counted both in the offsetLeft and in the
clientLeft.
If I add up all offsetLeft+clientLeft values, I get the wrong result.
In the case of TABLE (maybe others?) I need to ignore the clientLeft value.

Please feel free to disregard the below as the next VK's nonsense.

An *exact* position of HTML element in *any* given situation is another
perpetuum mobile of the web which people are trying to invent for 8
years in the row. The problem *has* an exact numeric solution in each
given situation. But: the amount of given situations is Infinity. I
presume this kind of problem has a special term in math. So you can
extend your formula to cover as many situations as you can think of,
but you still have Pr[x] in your low members.
Nothing will change until W3C will finally invent (and other support)
something like:
element.layoutFrameLeft
element.layoutFrameTop
element.vewportLeft
element.vewportRight
Right now W3C is preoccupated by much more important things like
defining the exact type of JavaScript block: should it be
"text/javascript" or "application/javascript". But eventually they may
move on some minor problems like the one further above.

Until then all these offsetHere / offsetThere is a bunch of useless
obscure crap. No one would even know about them in a normal situation.

If you are really targeted to write the most universal solution (but
still *not* absolutely universal) I would suggest to drop these "toys
for poors" (offsetLeft / offsetRIght) and try to read the graphics
layout directly. On of old tricks is to use the "event sonar" like
below (please disregard the ansient formatting). If you want more
coverage (as event sonar works well for IE only) you can use the
"scanner method": run invisible div "scanlines" from 0 to page bottom
and from 0 to page right until they hit the element of question. There
are other methods - but you've got the idea.

<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
<script>
function sonar() {
document.body.attachEvent('onclick',echo);
var evt = document.createEventObject();
document.getElementById('Layer3').fireEvent('onclick',evt);
}
function echo() {
alert(event.screenX);
}
</script>
</head>

<body bgcolor="#FFFFFF" onload="sonar()">
<div id="Layer1" style="position:absolute; width:400px; height:400px;
z-index:1; left: 10px; top: 10px; background-color: #FFFF99;
layer-background-color: #FFFF99; border: 1px none #000000">
<div id="Layer2" style="position:absolute; width:200px; height:200px;
z-index:1; left: 100px; top: 100px; background-color: #99FF33;
layer-background-color: #99FF33; border: 1px none #000000">
<div id="Layer3" style="position:absolute; width:100px; height:100px;
z-index:1; left: 50px; top: 50px; background-color: #33FF99;
layer-background-color: #33FF99; border: 1px none #000000"></div>
</div>
</div>

</body>
</html>
 
J

Jim Ley

Right now W3C is preoccupated by much more important things like
defining the exact type of JavaScript block: should it be
"text/javascript" or "application/javascript".

The W3C did not specify this, Bjoern Hoerhrmann did, whilst Bjoern is
an Invited Expert to the CSS working group, he is not any more part of
the W3C nor was the ecmascript registration done with any connection
to his W3C stuff.
Until then all these offsetHere / offsetThere is a bunch of useless
obscure crap.

I would've thought the W3C's web-apps WG would specify something that
looks almost identical to the offsetLeft offsetParent method available
today.

Jim.
 
V

VK

Jim said:
I would've thought the W3C's web-apps WG would specify something that
looks almost identical to the offsetLeft offsetParent method available
today.

This is why there are two equally terrible things which *may* happen
with the Web Community: i) W3C becomes the only and ultimate authority
or ii) W3C disappears, taking down all standard-based wannabes and
Internet Explorer becomes the only king.

Both situations should be avoided by all possible means, at least until
Firefox gets strong enough to hold two fingers at once: one for
Microsoft, other for W3C's step-parents.

P.S. I have a creative proposal :) Anyone who quotes W3C standards
more then say 20 times per month in this group should be penalizing for
one week of browsing and posting (via groups.google.com) only using W3C
Amaya <http://www.w3.org/Amaya/User/BinDist.html>
What would learn someone to simple joy of the "loose Web" and to
buseness (as opposed to academical) thinking. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top