为什么我的绝对/固定定位元素没有位于我期望的位置?

2022-01-30 00:00:00 html css css-position

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

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

.container {背景:浅蓝色;位置:相对;}.box-橙色 {背景:橙色;高度:100px;宽度:100px;位置:相对;顶部:100 像素;左:100px;z指数:2;}.box-蓝色 {背景:天蓝色;高度:100px;宽度:100px;/*位置:静态;*/}.box-green {背景:浅绿色;高度:100px;宽度:100px;位置:相对;顶部:-105px;左:105px;z指数:2;}.box-灰色 {背景:灰色;高度:100px;宽度:100px;位置:绝对;}

<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 {背景:浅蓝色;位置:相对;}.box-橙色 {背景:橙色;高度:100px;宽度:100px;位置:相对;顶部:100 像素;左:100px;z指数:2;}.box-蓝色 {背景:天蓝色;高度:100px;宽度:100px;/*位置:静态;*/}.box-green {背景:浅绿色;高度:100px;宽度:100px;位置:相对;顶部:-105px;左:105px;z指数:2;}.box-灰色 {背景:灰色;高度:100px;宽度:100px;位置:绝对;}

<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' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = 包含块的高度

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

'top' + 'margin-top' + 'height' + 'margin-bottom' + 'bottom' = 包含块的高度

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

<块引用>

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

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

<块引用>

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

为了简单起见,如果你没有设置position:absolute,它就是元素的位置.

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

.container {背景:浅蓝色;位置:相对;填充:40px 20px;显示:内联块;垂直对齐:顶部;宽度:250px;}.box-灰色 {背景:灰色;高度:100px;宽度:100px;位置:绝对;}.box-green {高度:20px;背景:绿色;}

<div class="container"><div class="box-green"></div><div class="box-grey" style="position:static;">我是静态的</div></div><div 类="容器"><div class="box-green"></div><div class="box-grey">我是绝对的</div></div>

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

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

<块引用>

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

.container {背景:浅蓝色;位置:相对;填充:40px 20px;显示:内联块;垂直对齐:顶部;宽度:250px;}.box-灰色 {背景:灰色;高度:100px;宽度:100px;位置:绝对;顶部:0;}.box-green {高度:20px;背景:绿色;}

<div class="container"><div class="box-green"></div><div class="box-grey" style="position:static;">我是静态的</div></div><div 类="容器"><div class="box-green"></div><div class="box-grey"></div></div>

同样的逻辑适用于 left 属性


您可能还会注意到这里使用了非常重要的词包含块,并在相同规范

<块引用>

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

...

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

...

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

相关:为什么在父级上应用 CSS-Filter 会破坏子级定位?

I'm just learning the positioning in CSS. Based on the article that I've found useful, I'd started to playing around.

With the following code, I cannot understand why the absolute grey-box div is outside of it's relative parent. I expected that the grey-box will be on the top-left corner of the container.

.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>

Also can't understand in the following case why the grey-box not in the top-left corner, but moved after the empty space left by the orange-box there. I've just moved the grey-box to the second place inside the container 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>

All the detailed documentation (e.g. MDN) and tutorials that I've found just demonstrating very simple examples with 2-3 boxes.

解决方案

To correctly understand this, you need to refer to the official specification where you find the equation the element must satisfy:

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

We don't have any border and padding so in your case it will simply be:

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

And if you read under you will find this:

  1. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then set 'top' to the static position, set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'.

So in your case, you have set a height and kept top/bottom to auto thus top will be set to static position

..More precisely, the static position for 'top' is the distance from the top edge of the containing block to the top margin edge of a hypothetical box that would have been the first box of the element if its specified 'position' value had been 'static'..

To make it easy, it's the position of the element if you didn't set position:absolute.

Here is an easy illustration to better understand

.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>

Note the static position of the first element that is kept if we add position:absolute. We didn't specify any top value so the browser will use a default one that is the one of the position:static (default position) of the element.

If you don't want this, simply set the top value and you fall into this rule:

  1. 'bottom' is 'auto', 'top' and 'height' are not 'auto', then set 'auto' values for 'margin-top' and 'margin-bottom' to 0 and solve for '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>

Same logic apply to the left property


You may also notice the use of the word containing block which very important here and explained in the same specification

The position and size of an element's box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element. The containing block of an element is defined as follows:

...

  1. If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way:

...

And it's not enough as there is other properties (listed below) that also establish a containing block so you can have an element positionned relatively to an ancestor that is not positionned!

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

相关文章