为什么 "position: relative" 会干扰 "transform: scale"?

Why does "position: relative" interfere with "transform: scale"?

给定以下标记和样式

div {
  width: 300px;
  height: 50px;
  border: 1px solid black;
  display: inline-block;
  transition: all .1s ease-in-out;
  background-color: white;
  padding: 0px 5px;
}
div:hover {
  transform: scale(1.2);
}
label {
  /*position: relative;*/
}
<div>
  <label>some random text</label>
</div>
<div>
  <label>some random text</label>
</div>

当鼠标悬停在第一个 div 上时,第二个 div 中的某些字母正在 "hidden" 缩放元素下方。但是,当在 label 元素上设置 position: relative 时,文本将呈现在缩放元素上:

div {
  width: 300px;
  height: 50px;
  border: 1px solid black;
  display: inline-block;
  transition: all .1s ease-in-out;
  background-color: white;
  padding: 0px 5px;
}
div:hover {
  transform: scale(1.2);
}
label {
  position: relative;
}
<div>
  <label>some random text</label>
</div>
<div>
  <label>some random text</label>
</div>

我正在尝试理解这背后的原因。由于这种接缝跨浏览器是一致的,我认为它是在规范中定义的。如果是这样,理由是什么?还有我怎么"turn it off",如果摸不到相对定位呢?

对元素应用转换会导致它建立新的堆叠上下文。

定位元素(即将其 position 设置为 static 以外的其他内容)不一定会导致它建立堆叠上下文,特别是相对定位的元素 z-index: auto(默认值)不建立堆叠上下文。

话虽如此,两种类型的元素都按照 section 9.9 of CSS2.1 中定义的绘制顺序组合在一起:

Within each stacking context, the following layers are painted in back-to-front order:

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

当您悬停第一个 div 时,它成为堆栈级别为 0 的子堆栈上下文,但此子堆栈上下文与第二个 label 中的子堆栈上下文参与相同的父堆栈上下文 div 因为第二个 div 本身不建立堆栈上下文。

由于您的所有元素都具有相同的堆栈级别 0(基于默认值 z-index: auto),规范说:

Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.

由于您的第一个 div 发生在第二个 divits label 之前,因此第二个 label div 被绘制在第一个 div 上,尽管进行了变换。

您可以通过在 div:hover 上指定 z-index: 1 来解决此问题:

div {
  width: 300px;
  height: 50px;
  border: 1px solid black;
  display: inline-block;
  transition: all .1s ease-in-out;
  background-color: white;
  padding: 0px 5px;
}
div:hover {
  transform: scale(1.2);
  z-index: 1;
}
label {
  position: relative;
}
<div>
  <label>some random text</label>
</div>
<div>
  <label>some random text</label>
</div>