So reverse engineering offsetLeft
, offsetTop
and offsetParent
has been fun. I still have to cover some of the more complex cases in the specification like how it works for frame based pages or rotated HTML content, but I’m getting there. The specification also talks about objects implementing the HTMLBodyElement
, while it should be talking about document.body
or the
as HTML5 refers to it given that multiple objects within the page could implement that interface after some DOM tricks.
body
element,
Anyway, before I made this revision we (at Opera) thought of something clever that would not need the body
element “hack” and would allow people to determine the position of that element as well, by removing body
from and putting html
in the offsetParent
chain plus assuming authors won’t style html
normally. (If it was styled, you could still get an accurate position by querying offsetLeft
and offsetTop
on html
, but normal scripts wouldn’t because they stop when offsetParent
hits null
.) Morten implemented this and it was working all nice and dandy, until we broke hotmail.com nearing the release of Opera 9 final! Oops, not our intention! The plan was to actually improve our offset attributes just before the final release, not to cause regressions.
So we came up (quite quickly actually) with a better algorithm that would not fail with obj.offsetParent != document.body
kind of code. We changed html
back to body
, but instead of actually calculating against the body
element itself (as we used to do) we decided upon a special quirk that’s more or less what other browsers do as well. Namely that when offsetParent
is document.body
offsetLeft
and offsetTop
are calculated against the initial containing block instead of the border edge of the body
element. Fun stuff! The consequence of this is that offsetLeft
and offsetTop
are always zero for the body
element.