【问题标题】:Why aren't my absolutely/fixed-positioned elements located where I expect?为什么我的绝对/固定定位元素没有位于我期望的位置?
【发布时间】:2021-01-17 01:59:27
【问题描述】:

我只是在学习 CSS 中的定位。根据我发现有用的文章,我开始玩弄。

使用下面的代码,我无法理解为什么绝对的灰盒 div 在它的相对父级之外。我预计灰色框会在容器的左上角。

.container {
  background: lightblue;
  position: relative;
}

.box-orange {
  background: orange;
  height: 100px;
  width: 100px;
  position: relative;
  top: 100px;
  left: 100px;
  z-index: 2;
}

.box-blue {
  background: lightskyblue;
  height: 100px;
  width: 100px;
  /*position: static;*/
}

.box-green {
  background: lightgreen;
  height: 100px;
  width: 100px;
  position: relative;
  top: -105px;
  left: 105px;
  z-index: 2;
}

.box-grey {
  background: grey;
  height: 100px;
  width: 100px;
  position: absolute;
}
<div class="container">
  <div class="box-orange"></div>
  <div class="box-blue"></div>
  <div class="box-green"></div>
  <div class="box-grey"></div>
</div>

在以下情况下也无法理解为什么灰色框不在左上角,而是在橙色框留下的空白区域之后移动。我刚刚将灰色框移到容器 div 内的第二个位置。

.container {
  background: lightblue;
  position: relative;
}

.box-orange {
  background: orange;
  height: 100px;
  width: 100px;
  position: relative;
  top: 100px;
  left: 100px;
  z-index: 2;
}

.box-blue {
  background: lightskyblue;
  height: 100px;
  width: 100px;
  /*position: static;*/
}

.box-green {
  background: lightgreen;
  height: 100px;
  width: 100px;
  position: relative;
  top: -105px;
  left: 105px;
  z-index: 2;
}

.box-grey {
  background: grey;
  height: 100px;
  width: 100px;
  position: absolute;
}
<div class="container">
  <div class="box-orange"></div>
  <div class="box-grey"></div>
  <div class="box-blue"></div>
  <div class="box-green"></div>
</div>

我发现的所有详细文档(例如 MDN)和教程只是用 2-3 个框演示了非常简单的示例。

【问题讨论】:

  • 您没有设置任何 top/left .. 设置 top/left 来控制位置,否则它将根据其 static 位置进行定位。由于您仍在学习,因此无需对默认位置感到困惑

标签: html css css-position


【解决方案1】:

要正确理解这一点,您需要参考official specification,您可以在其中找到元素必须满足的方程式:

'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block

我们没有任何边框和填充,所以在您的情况下,它只是:

'top' + 'margin-top' + 'height' + 'margin-bottom' + 'bottom' = height of containing block

如果您阅读下面的内容,您会发现:

  1. 'top' 和 'bottom' 是 'auto' 而 'height' 不是 'auto',然后将 'top' 设置为静态位置,将 'auto' 值设置为 'margin- top' 和 'margin-bottom' 为 0,并求解 'bottom'。

因此,在您的情况下,您已设置高度并将 top/bottom 保持为自动,因此顶部将设置为 静态位置

..更准确地说,'top' 的静态位置是从包含块的顶部边缘到假设框的顶部边缘边缘的距离,如果它指定了 'position '值一直是'静态'..

为方便起见,如果你没有设置position:absolute,它是元素的位置。

这是一个简单的插图,可以更好地理解

.container {
  background: lightblue;
  position: relative;
  padding:40px 20px;
  display:inline-block;
  vertical-align:top;
  width: 250px;
}


.box-grey {
  background: grey;
  height: 100px;
  width: 100px;
  position: absolute;
}

.box-green {
  height:20px;
  background:green;
}
<div class="container">
  <div class="box-green"></div>
  <div class="box-grey" style="position:static;">I am static</div>
</div>

<div class="container">
  <div class="box-green"></div>
  <div class="box-grey">I am absolute</div>
</div>

如果我们添加position:absolute,请注意保留的第一个元素的静态位置。我们没有指定任何顶部值,因此浏览器将使用默认值,即元素的 position:static(默认位置)之一。

如果你不想这样,只需设置顶部值,你就会陷入这个规则:

  1. 'bottom' 是 'auto','top' 和 'height' 不是 'auto',然后将 'margin-top' 和 'margin-bottom' 的 'auto' 值设置为 0 并求解 'bottom'

.container {
  background: lightblue;
  position: relative;
  padding:40px 20px;
  display:inline-block;
  vertical-align:top;
  width: 250px;
}


.box-grey {
  background: grey;
  height: 100px;
  width: 100px;
  position: absolute;
  top:0;
}

.box-green {
  height:20px;
  background:green;
}
<div class="container">
  <div class="box-green"></div>
  <div class="box-grey" style="position:static;">I am static</div>
</div>

<div class="container">
  <div class="box-green"></div>
  <div class="box-grey"></div>
</div>

同样的逻辑适用于the left property


您可能还注意到这里使用了非常重要的词包含块,并在same specification中进行了解释

元素框的位置和大小有时是相对于某个矩形计算的,称为元素的包含块。元素的包含块定义如下:

...

  1. 如果元素具有“位置:绝对”,则包含块由“位置”为“绝对”、“相对”或“固定”的最近祖先建立,方式如下:

...

这还不够,因为还有其他属性(如下所列)也建立了一个包含块,因此您可以将元素相对于未定位的祖先定位!

相关:Why does applying a CSS-Filter on the parent break the child positioning?

【讨论】:

    【解决方案2】:

    您必须始终在绝对定位的元素上设置top:0; left:0;(或您想要的顶部、右侧、底部、左侧的任何值)。

    【讨论】:

    • 必须始终 --> 不是必须的,这样会更容易
    • From the MDN >> 元素从正常的文档流中移除,并且在页面布局中没有为元素创建空间。它相对于其最近的定位祖先(如果有)进行定位;否则,它相对于初始包含块放置。它的最终位置由顶部、右侧、底部和左侧的值决定。这就是我无法理解的为什么我需要使用偏移量
    【解决方案3】:

    首先,元素是相对于它的第一个定位(非静态)祖先元素定位的。

    在这种情况下,绝对位置适用于兄弟,而不适用于祖先。

    关于祖先和兄弟姐妹,有一个关于它的神文档:Ancestors and siblings

    .container {
      background: lightblue;
      position: relative;
    }
    
    .box-orange {
      background: orange;
      height: 100px;
      width: 100px;
      position: relative;
      top: 100px;
      left: 100px;
      z-index: 2;
    }
    
    .box-blue {
      background: lightskyblue;
      height: 100px;
      width: 100px;
      /*position: static;*/
    }
    
    .box-green {
      background: lightgreen;
      height: 100px;
      width: 100px;
      position: relative;
      top: -105px;
      left: 105px;
      z-index: 2;
    }
    
    .box-grey {
      background: grey;
      height: 100px;
      width: 100px;
      position: absolute;
    }
    <div class="container">
      <div class="box-grey"></div>
      <div class="box-orange"></div>
      <div class="box-blue"></div>
      <div class="box-green"></div>
    </div>

    如果我将元素放在 div 容器之后,则一切正常

    Documentation of postion

    关于第二部分,那个框出现在那里是因为 box-gery 与 box-green 的顶部和右侧无关,明白吗?举个例子:

    .container {
      background: lightblue;
      position: relative;
    }
    
    .box-orange2 {
      background: orange;
      height: 100px;
      width: 100px;
      position: relative;
      z-index: 2;
    }
    
    .box-orange {
      background: orange;
      height: 100px;
      width: 100px;
      position: relative;
      top: 100px;
      left: 100px;
      z-index: 2;
    }
    
    .box-blue {
      background: lightskyblue;
      height: 100px;
      width: 100px;
      /*position: static;*/
    }
    
    .box-green {
      background: lightgreen;
      height: 100px;
      width: 100px;
      position: relative;
      top: -105px;
      left: 105px;
      z-index: 2;
    }
    
    .box-grey {
      background: grey;
      height: 100px;
      width: 100px;
      position: absolute;
    }
    
    .box-yellow {
      background: yellow;
      height: 100px;
      width: 100px;
      position: absolute;
    }
    <div class="container">
      <div class="box-orange2"></div>
      <div class="box-grey"></div>
      <div class="box-orange"></div>
      <div class="box-yellow"></div>
    </div>

    您可以看到,无论顶部和右侧是否在同级中,灰色和黄色框都不会改变行为。

    【讨论】:

    • 非常感谢 Alejandro 我想问你关于你提到的第一部分,因为它在每个文档中都有写:元素相对于它的第一个定位(非静态)祖先定位element 这对我来说意味着在这种情况下容器是第一个定位的祖先。为什么灰盒没有定位到它的位置?为什么它不在容器的左上角?
    • 嗨,box-grey 的祖先不是容器,它是 box-green。 box-green 位于顶部:-105px;和左边:105px;,如果你删除这个属性,你会看到那个盒子灰色,它就在盒子绿色的下面。那是因为祖先是在问候之前的元素
    • 所以但你说的是错误的,box-green 不是 box-grey 的祖先,它是一个兄弟元素。祖先不是 before 元素
    • 没错,抱歉。但是,属性位置与兄弟姐妹配合得很好,所以我认为祖先在顶部。
    • @MontyX 不!他不对。这是假的。就像我告诉你的那样,你必须设置top/left 属性才能看到想要的结果(top:0;left:0).. 并且祖先不是前一个元素
    猜你喜欢
    • 1970-01-01
    • 2013-06-16
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多