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!