css中position: absolute可以将元素指定为绝对定位,那么绝对定位元素的几何位置是相对于谁计算呢?
MDN上的描述是:
绝对定位元素相对于最近的非 static 祖先元素定位。当这样的祖先元素不存在时,则相对于ICB(inital container block, 初始包含块)。
也即是说,绝对定位元素应该相对其position为非static的最近祖先定位,或者这样的祖先不存在时相对初始包含快(一般为body)定位。而position默认为static。
但似乎有时候也有例外。
今天想在一个scroller组件中使用绝对定位突破到更顶层,但意外的发现,即使从该元素的父元素到body都没有指定position
属性,它竟然仍是相对scroller容器定位而不是body或者更上层的具有position: relative
属性的元素。
实验了半天发现是因为scroller使用了css的transform
属性来变换滚动元素的位置以提升性能。而这直接导致了具有有效transform
属性的元素成了绝对定位元素的基准。
考虑如下html:
<div style="line-height: 50px;">
<style>
.relative-container {
background: lightcoral;
position: relative;
height: 300px;
}
.midware {
background: lightcyan;
height: 200px;
}
.absolute-block {
background: black;
height: 30px;
position: absolute;
top: 0;
width: 30px;
}
</style>
<div class="relative-container">
------把下面的div撑下去一点方便观察差异-------
<div class="midware">
<div class="absolute-block"></div>
</div>
</div>
</div>
如上,absolute-block
成功突破了midware
,top: 0
是相对于relative-container
而不是其直接父元素midware
。但是当我们为midware
添加transform属性后:
.midware {
background: lightcyan;
height: 200px;
transform: translateZ(0);
}
absolute-block
已经相对其父元素midware
定位了!但midware
的position
并没有被显示指定。transform设置为其他有效值效果也一样。
为了测试transform属性是否隐式改变了position属性,我添加了如下代码:
const el = document.querySelector('.midware');
console.log(getComputedStyle(el).position); // static
并没有。这个现象应该是由其他机制引起的。
最后查了下资料,有人说是由层叠上下文导致的。但又不是所有的层叠上下文都会造成这样的影响,不同内核的浏览器也有不同的表现。所以应该将这个特性当作bug来对待?