绝对定位的元素会相对于被转换的元素进行定位。

3
我在一个模板中重新创建了一个问题,其中一个 navposition: relative;。在 nav 内部有一个嵌套两个列表的 div
其中一个列表是绝对定位的,以粘着到 nav 的底部。div 应用转换属性时会出现问题。
当绝对和相对定位元素之间的 div 获取变换属性时,绝对位置列表相对于 div 而不是 nav 定位。

MDN 文档关于 position:absolute 的说明如下

不为元素留出空间。相反,如果有,请将其相对于最近的已定位祖先(如果有)或相对于包含块定位。绝对定位的框可以具有边距,并且它们不与任何其他边距折叠。

这是否意味着转换的元素是定位元素?为什么会出现这种情况?我在 Edge、FF 和 Chrome 中进行了测试。它们都表现得一样。
您可以运行下面重新创建的代码片段。我在 nav 上悬停时应用 div 上的转换。

*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html, body{
  min-height: 100%;
  height: 100%;
}
nav{
  background: #000;
  height: 100%;
  width: 50%;
  position: relative;
}
nav:hover > div{
      transform: translateX(50px) translateY(0) translateZ(0);
}
a{
  color: #fff;
}
ul{
  padding: 16px;
}
ul.main{
  background: blue;
}

ul.lower{
  position: absolute;
  background: red;
  bottom: 0;
  width: 100%;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<nav>
  <div>
    <ul class="main">
      <li><a href="">link</a></li>
      <li><a href="">link</a></li>
      <li><a href="">link</a></li>
      <li><a href="">link</a></li>
    </ul>
    <ul class="lower">
      <li><a href="">link</a></li>
      <li><a href="">link</a></li>
      <li><a href="">link</a></li>
      <li><a href="">link</a></li>
    </ul>
  </div>
</nav>
</body>
</html>


我知道我可以通过更改HTML来解决它,但在模板限制的情况下我无法这样做。而且我更好奇为什么会出现这种情况,而不是解决方案本身。 - Swimburger
这里是相同的代码在 jsbin 上的链接 https://jsbin.com/covesawupu/edit?html,css,js,output - Swimburger
2
我相信我们可以在这里找到答案:MDN Transform ... 它说:“如果属性具有与none不同的值,则将创建堆叠上下文。”(在这种情况下,“该属性”是指变换属性)... 这里有一些关于堆叠上下文的信息。 - Carlos Mateo
@CarlosMateo 是的,这似乎解释了为什么它会以这种方式运作。谢谢您提供的参考,这很有趣。如果您发布一个答案,我会接受它。 - Swimburger
3个回答

6
CSS规范规定,在元素上定义transform属性会创建一个包含块(详见规范)

对于其布局受CSS盒模型约束的元素,除了none值外,任何值设置transform属性,都会创建一个堆叠上下文和包含块。

根据规范(详见规范):

在绝对定位模型中,盒子相对于其包含块明确偏移。

关键在于将元素的transform属性设置为任何非none值都会创建一个新的包含块,而堆叠上下文与元素定位方式无关,请参见下面代码片段中的示例。

body {
  padding-top: 100px;  
}

.containing-block,
.stacking-context {
  height: 50px;
  padding-top: 50px;
}

.containing-block {
  background-color: hotpink;
  /* transform with a value other than none defines both a containing block and a stacking context. */ 
  transform: scale(1);
}

.stacking-context {
  background-color: orange;
  /* opacity with a value other than 1 defines a stacking context but no containing block. */
  opacity: .99;
}

.abs{
  position: absolute;
  top: 0;
    
  padding: 10px;

  background-color: dodgerblue;
}
<body>
  <div class="containing-block">1: transform: scale(1);
    <div class="abs">1: Containing block example</div>
  </div>

  <div class="stacking-context">2: opacity: .99
    <div class="abs">2: Stacking context example</div>
  </div>
</body>


0

如果你将转换应用于.main而不是div,它似乎按预期工作。


我正在寻找为什么它会这样行为的答案,而不是通过更改HTML或CSS来解决它的方法。谢谢你抽出时间来看这个问题。 - Swimburger
哦,好的。你只提到不更改HTML,所以我认为这对你有用。 - Brian Glaz

-1

1
堆叠上下文与此无关,它影响 z-index。正确答案是它还创建了一个包含块。 - Razvan Cercelaru
请查看此链接以获取包含块的相关信息。 - David Long

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接