Given two abitrary HTML elements A and B in the same document, how can I find out which one is "closer" to the user (i.e. if they overlap, which one is obscuring the other)?
The W3C CSS Specification describes stacking contexts, which compliant rendering engines should implement. However, I couldn't find a way to access this information in a JavaScript program, cross-browsers or not. All I can read is the css z-index
property, that per se doesn't say much, since most of the time is set to auto
or, even when expressed as a numeric value, is not a reliable indicator of how it's actually displayed (if they belong to different statcking contexts, comparing z-indexes is irrelevant).
Please note that I'm interested in arbitrary elements: if both elements are below the mouse pointer, only one will be considered "hovered", so I can easily find the closest one in this case. However, I'm looking for a more general solution, preferably one that does not involve re-implementing the stacking algorithm that the rendering engine is already performing.
Update: let me clarify a bit the reason behind this question: I recently tackled a question that exposed a limitation in jQuery's drag and drop mechanism - it doesn't take z-indexes into account when dropping, so if an element is obscuring another, it can still perform the drop operation in the element that is "behind". While the linked question was answered for the OP particular case, the general problem persists, and there's no easy solution that I know of.
alex's answer below is useful, but not enough for the case at hand: when dragging, the dragged element itself (or more precisely its helper) is the topmost element under the mouse cursor, so elementFromPoint
will return it instead of the next topmost element, that we really need (workaround: style the cursor so it's placed outside the helper). The other intersection strategies that jQuery employ also take into account more than just one point, complicating the task of determining the topmost element that intersects the helper somehow. Being able to compare (or sort) elements by actual z-index would make a "z-index aware" intersection mode viable for the general case.