How to Determine Positions of Elements
The first question is: relative to what? The window? The document?
Another element? Do you instead want the CSS position? Backing up
further, for what are the coordinates to be used?
Determining the position of elements relative to the window is mostly
trivial. Use the getBoundingClientRect method.
With simplified feature detection*:-
if (document.documentElement &&
document.documentElement.getBoundingClientRect) {
var getPositionRelativeToWindow = function(el) {
var rect = el.getBoundingClientRect();
return [rect.left, rect.top];
};
}
This method is a Microsoft invention, but has been copied widely and
is now pervasive (and pending some sort of retroactive
"standardization").
http://msdn.microsoft.com/en-us/library/ms536433(v=vs.85).aspx
As per usual, the MS documentation is horrible:-
"In Microsoft Internet Explorer 5, the window's upper-left is at 2,2
(pixels) with respect to the true client."
ISTM this method was in IE 4, but that's irrelevant today. But what
about 6, 7, 8, 9, 10, ... ? And what's this "true client" thing?
What they meant to say is that in IE, the border of the HTML element
(BODY in quirks mode) is part of the chrome and therefore user-
configurable. The default of 2 is the default for the Windows OS at
the time (circa 1999?) this documentation was written. It can be
trumped by the border-width style as well. IE measures from the top
left corner of the border. In short, this is not the case with
virtually any other browser (other than IE clones). Where IE will
often return [2,2], others will return [0,0].
So this method is supported by virtually every browser in use today
(excluding old versions of FF, Opera, etc.), but there is a minor
difference between the implementations. Fortunately, the difference is
easily accounted for (by subtracting the clientLeft/Top values of HTML
or BODY); but, depending on context, it may not need to be.
For what are these coordinates to be used? If only to compare one set
of coordinates to another, the implementation difference is on both
sides of the equation. Comparing two sets of coordinates is required
to determine if one element overlaps another and that's the typical
use case for such functions.
This use case does not require figuring the position relative to the
document (which would require finding the scroll position). It does
require figuring the relative position of two elements, which can be
determined from the results of the above function.
As for positioning elements so that they overlap or are adjacent, the
above function can aid in that too. Get the coordinates of the
target, set the left and top styles of the element to be positioned
and then check its coordinates afterward. They may match by
coincidence, in which case you are done. If not, the difference
between the two is easily determined. Adjust the left and top styles
as needed.
As for CSS position:-
http://www.cinsoft.net/position.html
...is a far better bet than trying to use real or simulated
getComputedStyle. It uses the same set-test-adjust pattern as the
above.
What do you find for this sort of task in the typical library or
framework? A getBoundingClientRect wrapper that adds the scroll
position and tries to account for implementation differences that are
irrelevant in many contexts. Depending on the library, there may be
another (long-winded and over-complicated) fork that attempts to
simulate getBoundingClientRect by adding offsetLeft/offsetTop (and
sometimes clientLeft/Top) values for each of the element's offset
parents. That stuff is no more standardized than
getBoundingClientRect and the only benefit is that some long-since
shelved versions of Firefox and Opera can join in the fun. Suffice to
say, those alternate forks are not known for reliability; many employ
browser sniffing to "work".
Seems pretty silly to send such unneeded code to battery-powered
mobile devices, particularly when a two-liner can do the work for
virtually all browsers in use today. Of course, you can say that
about a large percentage of the JS on the Web. The libraries haven't
evolved and, due to their static nature, can't evolve in any sort of
controlled manner. In short, what happens to the old versions of IE
when the old IE hacks are (finally) removed? Users of old IE get
broken sites and applications. Much as they might like to think so,
most end-users don't choose browsers based on the advice of JS library
authors. That segment of the population is not clamoring for the next
cool version of jQuery (or whatever). They want sites to load and
respond quickly, not to break or contribute to their browser crashing
(as often happens on overwhelmed mobile devices).
http://en.wikipedia.org/wiki/Cargo_cult_programming
* Use isHostObjectProperty (or the like) to detect
document.documentElement and isHostMethod to detect
getBoundingClientRect.
http://www.cinsoft.net/
http://www.twitter.com/cinsoft
http://jsperf.com/browse/david-mark