【问题标题】:Absolutely positioned element positions relatively to transformed element相对于变换元素的绝对定位元素位置
【发布时间】:2016-08-18 17:31:50
【问题描述】:

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

MDN Docs state the following about position:absolute

不要为元素留出空间。相反,将其放置在 相对于其最近定位的祖先的指定位置(如果有), 或以其他方式相对于包含块。绝对定位 框可以有边距,并且它们不会与任何其他框一起折叠 边距。

这是否意味着转换后的元素是定位元素? 为什么这样做?我在 Edge、FF 和 Chrome 中进行了测试。他们的行为都一样。

您可以在下面运行重新创建的 sn-p。我在导航悬停时在 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 来解决它,但是在模板给我的限制的情况下我不能 + 我更好奇为什么它会以这种方式而不是解决方案本身
  • 这里是jsbin上相同的代码jsbin.com/covesawupu/edit?html,css,js,output
  • 我相信我们可以在这里找到答案:MDN Transform ...它说:“如果属性的值不同于无,将创建一个堆叠上下文。” (在这种情况下,“属性”指的是变换属性)......这里有一些关于 stacking context 的信息
  • @CarlosMateo 是的,这似乎解释了它为什么会这样。谢谢你的参考,这很有趣。如果您发布答案,我会接受。

标签: css css-position transform css-transforms


【解决方案1】:

CSS 规范声明 defining a transform on an element creates a containing block:

对于布局由 CSS 框模型控制的元素,除了 none 之外的任何转换值都会导致创建堆叠上下文和包含块。

还有(see spec):

在绝对定位模型中,一个盒子相对于它的包含块显式偏移。




这里的关键是,将元素的transform 属性设置为none 以外的任何值,会创建一个新的包含块堆叠上下文与元素的定位方式无关。

请参阅以下 sn-p 中的示例。

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>

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我正在寻找为什么它会以这种方式运行的答案,而不是如何通过更改 HTML 或 CSS 来解决它。不过,感谢您抽出宝贵的时间。
    • 哦,好的。您只提到不更改 HTML,所以我认为这对您有用。
    【解决方案3】:

    基本上因为任何应用了 transform 属性的元素,都会自动触发新的堆叠顺序:https://developer.mozilla.org/en-US/docs/Web/CSS/transform

    “如果该属性的值不是none,则将创建一个堆叠上下文。在这种情况下,该对象将充当位置的包含块:它包含的固定元素。”

    这里有一些关于堆叠上下文的额外信息:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context

    【讨论】:

    • 堆叠上下文与它没有任何关系,这会影响 z-index。正确答案是它还创建了一个包含块。
    • 检查 this 是否包含块
    猜你喜欢
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    相关资源
    最近更新 更多