Given two arbitrary HTML elements A and B on the same page, how can I find which one is "closest" to the user (i.e. if they overlap, which one would obscure the other)?
The W3C CSS specification describes "stacking contexts" ( stacking contexts ), that the rendering engines that follow the standards should implement. However, I could not find a way to access this information via JavaScript. All I have access to is the css z-index
property, which by itself does not say much, since in most cases it is auto
and - even when expressed by a number - is not a reliable indicator of how the elements are actually displayed (because if they belong to different stacking contexts, comparing z-indexes is irrelevant).
Note: I'm interested in arbitrary elements; if both are under the mouse pointer, only one will be considered "hovered" , so determining the closest is trivial. Likewise, if I know they intersect at a particular point, I can use document.elementFromPoint()
as suggested by in that answer in the English OS. However, it may not be the case that I know a point like this, or even that it exists - the elements may have no intersection with each other.
Is there a general solution to this problem, preferably one that does not involve reimplementing the stacking algorithm that the render engine is already doing anyway?
Motivation: There is a limitation on the drag-and-drop functionality of jQuery where you can not decide for sure where to drop a dragged element:
OldversionsofjQuerywouldchooseoneofthemratherthanrandom,whilerecentversionswilldothedropinboth(moredetailsonthat#). The ideal would be to choose just one of them - the one that is "closest to the screen" - and make the drop only in it, and for that I need a correct way to determine its actual z- even though this involves "re-inventing the wheel" as long as the result is consistent with the browser stack ).
* Another option, as pointed out by @utluiz, would be to take the intersection area into account when determining the correct target - either requiring the helper to be fully contained in (for example, if it is visually clear which is the correct target, but a helper tip touches a different element). But unfortunately, even to correctly calculate this area of intersection it is necessary to know the relative z-indexes, as it changes if one obscures the other.
Update: A seemingly complete solution was posted on SOen , full code is on GitHub and there is a usage example no jsFiddle . At first glance it looks ok, but any additional feedback would be very welcome. If everything is correct, post here as an answer.