Anne van Kesteren

Offset attributes again

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 body element, as HTML5 refers to it given that multiple objects within the page could implement that interface after some DOM tricks.

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 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.