Let's say we have the following setup:
#header {
background-color: #ddd;
padding: 2rem;
}
#containing-block {
background-color: #eef;
padding: 2rem;
height: 70px;
transform: translate(0, 0);
}
#button {
position: fixed;
top: 50px;
}
<div id="header">header</div>
<div id="containing-block">
containing-block
<div>
<div>
<div>
<button id="button" onclick="console.log('offsetParent', this.offsetParent)">click me</button>
</div>
</div>
</div>
</div>
where the button has fixed
position and the containing-block has a transform
property in place.
This might come as a surprise, but the button is positioned relative to the #containing-block
, not the viewport (as one would expect when using fixed
). That's because the #containing-block
element has the transform
property set. See https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed for clarification.
Is there an easy way to find out which is the containing block of the button? Which is the element top: 50px
is calculated in respect to? Assume you don't have a reference to the containing block and you don't know how many levels up it is. It may even be the documentElement if there are no ancestors with transform
, perspective
or filter
properties set.
For absolute
or relative
positioned elements, we have elem.offsetParent
which gives us this reference. However, it is set to null for fixed
elements.
Of course, I could look up the dom and find the first element that has a style property of transform
, perspective
or filter
set, but this seems hacky and not future proof.
Thanks!
offsetParent
is returning the right value. Chrome and other browsers are reportingnull
but it seems to be a bug. I filed a bug report bugs.chromium.org/p/chromium/issues/detail?id=1086125 – Cahra