为什么重叠元素的背景不能覆盖内容?

25

这是情况:

body {
  margin: 0;
  background: pink;
  color: #fff;
}

.box {
  margin-top: 20px;
  background: red;
}

.bottom {
  text-align: right;
  background: green;
  animation: animate 2s infinite alternate linear;
}

@keyframes animate {
  from {
    margin-top: 10px;
  }
  to {
    margin-top: -40px;
  }
}
<div class="box">
  some content
</div>
<div class="bottom">
  other content
</div>

发生了什么?

正如您所看到的,我们有两个没有任何复杂样式的 div(仅有背景颜色)。我通过应用负 margin-top 来使第二个 div 重叠在第一个上面。我希望看到一个 完全覆盖 另一个,但事实并非如此。第二个 div 在第一个的内容和背景之间滑动,这对我来说是一种 奇怪 的行为。

这里与动画无关,我只是用它来更好地展示这种行为。我们可以简单地添加负边距而不使用动画,就会得到相同的结果:

body {
  margin: 0;
  background: pink;
  color: #fff;
}

.box {
  margin-top: 20px;
  background: red;
}

.bottom {
  margin-top:-10px;
  text-align: right;
  background: green;
}
<div class="box">
  some content
</div>
<div class="bottom">
  other content
</div>

我的问题是:为什么会出现这样的行为?


顺便说一下,我们都知道在CSS中存在一些棘手的问题,当我们第一次面对它们时并不会怀疑(例如margin折叠,从body到html的背景传播,空格问题等),但是它们在某处被清楚地解释了。我希望能找到一个官方资源,在那里我可以清楚地理解这个问题,并且不仅仅得到像"也许这是因为...""我怀疑这与...有关""我认为这与...有关"之类的东西。


我对此的看法/解释

我认为文本等内容比背景和其他视觉样式更重要,因此当我们有重叠的情况时,我们将所有文本放置在顶部,将所有其他样式放置在底部,我们决定每个组内部的顺序,然后输出结果。

以下是一个更复杂的例子:

body {
  margin: 0;
  background: pink;
  color: #fff;
}

div {
  font-size: 39px;
  line-height: 28px;
  margin-bottom: -20px;
  font-weight: bold;
}

body :nth-child(1) {
  background: red;
  border:3px solid brown;
}

body :nth-child(2) {
  background: blue;
  border:3px solid yellow;
  color: #000;
}

body :nth-child(3) {
  background: green;
  border:3px solid orange;
}
<div>
  some content
</div>
<div>
  other content
</div>
<div>
  more content
</div>

我们可以清楚地看到,视觉堆栈如下(从下到上):

  • 第一个 div 的样式(背景 + 边框)
  • 第二个 div 的样式(背景 + 边框)
  • 第三个 div 的样式(背景 + 边框)
  • 第一个 div 的文本内容
  • 第二个 div 的文本内容
  • 第三个 div 的文本内容

重要提示:在回答之前,请注意我不是在寻求解决方法或如何避免这种情况。仅通过添加position:relative就可以消除这种行为,然后我们可以使用z-index来决定堆叠顺序。我想了解为什么会发生这种情况。


为什么具有不透明背景的同一图层上的文本重叠? - Danield
@Danield 啊!我很确定那里有一个重复的 :) [我在问题中也提到了,但由于没有人表现出来,所以我删除了通知]...顺便说一句,我看到你遇到了同样的问题,我们向你展示了规范,即使有规范,你仍然有点困惑...而且没有明确的原因说明为什么它应该是这样,而不是我们期望的那样 :/ - Temani Afif
1
是的,这非常违反直觉...顺便说一下,尽管基本问题相同,但我不会称您的问题为重复,因为您还在问为什么规范必须像这样。为什么也没有在回答我的问题中解释清楚。我很想知道是否有人能够解释这个问题,谢谢!+1 - Danield
这种行为只会在您使用负值属性时发生吗?还是正值也会出现这种情况? - Yvonne Aburrow
@YvonneAburrow 这是另一个上下文 :) 具有 z-index 的定位元素会被不同地处理[您可以仔细阅读规范]... 在这里,我们处于没有定义 z-index 的流内元素的情况下,因此提出了问题的目的... 这是一个非常特殊的情况 ;) - Temani Afif
显示剩余9条评论
8个回答

35

警告:阅读以下信息可能会影响您的心理健康。

堆叠上下文由产生堆叠上下文的元素后代生成,它们的绘制顺序如下:
  1. 如果元素是根元素:
    1. 元素的背景颜色覆盖整个画布。
    2. 元素的背景图像在整个画布上锚定在原点处,如果为根元素绘制,则使用该原点。
  2. 如果元素是一个块级元素、列表项或其他块等效物:
    • 元素的背景颜色,除非它是根元素。
    • 元素的背景图像,除非它是根元素。
    • 元素的列规则。
    • 元素的边框。
  3. 否则,如果元素是块级表格:
    1. 表格背景(颜色然后是图像),除非它是根元素。
    2. 列组背景(颜色然后是图像)。
    3. 列背景(颜色然后是图像)。
    4. 行组背景(颜色然后是图像)。
    5. 行背景(颜色然后是图像)。
    6. 单元格背景(颜色然后是图像)。
    7. 多列单元格列规则。
    8. 所有表格边框(以树形顺序分隔边框)。
  4. 按z-index顺序排列具有负z-index(不包括0)的定位后代生成的堆叠上下文,然后按树形顺序进行绘制。
  5. 对于其所有流动、非定位和块级后代,按树形顺序:
    • 如果元素是一个块级、列表项或其他块等效物:
      1. 元素的背景颜色。
      2. 元素的背景图像。
      3. 元素的列规则。
      4. 元素的边框。
    • 否则,元素是一个表格:
      1. 表格背景(颜色然后是图像)。
      2. 列组背景(颜色然后是图像)。
      3. 列背景(颜色然后是图像)。
      4. 行组背景(颜色然后是图像)。
      5. 行背景(颜色然后是图像)。
      6. 单元格背景(颜色然后是图像)。
      7. 多列单元格列规则(多列时)。
      8. 所有表格边框(以树形顺序分隔边框)。
  6. 所有非定位浮动后代,按树形顺序进行绘制。对于其中的每一个,将元素视为创建新的堆叠上下文,但任何定位后代和实际创建新的堆叠上下文的后代均视为父堆叠上下文的一部分,而不是新堆叠上下文的一部分。
  7. 如果元素是生成堆叠上下文的内联元素,则:
    1. 对于元素所在的每个行框:
      1. 跳转到该行框中该元素的盒子(按树形顺序)的7.2.1。
  8. 否则:首先为元素,然后按树形顺序为

    现在,严肃地参考w3c绘制顺序文档

    在4.1点中,子元素的背景被绘制

    在4.4点中,子元素的边框被绘制。

    当第4点完成时,你片段的所有背景和边框都已经被绘制了

    现在,在7.2.1.5.1.1.3点上,子元素的文本被绘制。

    这就是您看到的行为。

    还要注意,更改此行为很容易。我们可以激活第8.2点(设置不透明度),它将像您期望的那样绘制:

    body {
      margin: 0;
      background: pink;
      color: #fff;
    }
    
    .box {
      margin-top: 20px;
      background: red;
    }
    
    .bottom {
      text-align: right;
      background: green;
      animation: animate 2s infinite alternate linear;
      opacity: 0.9999;
    }
    
    @keyframes animate {
      from {
        margin-top: 10px;
      }
      to {
        margin-top: -40px;
      }
    }
    <div class="box">
      some content
    </div>
    <div class="bottom">
      other content
    </div>

    另一个片段,展示文档中的几个点:

    请注意,步骤4中的所有边框和背景都在步骤3之后、步骤5之前渲染。但是,步骤4中的文本是步骤7,因此在步骤5中的文本之后呈现。

    div {
      width: 200px;
      height: 100px;
      border: solid 10px;
      font-size: 40px;
    }
    
    .step3 {
      border-color: red;
      background-color: lightpink;
      z-index: -1;
      position: relative;
      margin-left: 10px;
    }
    
    .step41 {
      border-color: brown;
      background-color: yellow;
      margin-left: 30px;
      margin-top: -40px;
    }
    
    .step42 {
      border-color: blue;
      background-color: lightblue;
      margin-left: 50px;
      margin-top: -40px;
      color: red;
    }
    
    .step43 {
      border-color: green;
      background-color: lightgreen;
      margin-left: 160px;
      margin-top: -150px;
      color: crimson;
    }
    
    .step5 {
      float: left;
      background-color: white;
      margin-top: -30px;
    }
    
    div:hover {
      position: relative;
    }
    <div class="step3">Step 3 negative zindex</div>
    <div class="step41">step4 In flow, number 1</div>
    <div class="step42">In flow, number 2</div>
    <div class="step43">In flow, number 3</div>
    <div class="step5">step 5 float</div>

    我不知道这是否算作用例:这种情况下,元素相对定位的初始行为更加自然。

    div {
      width: 100px;
      height: 1.3em;
      border: solid 12px tomato;
      font-size: 18px;
    }
    
    div:hover {
      position: relative;
    }
    <div>a long stretch of text overflowing to the other div</div>
    <div></div>


1
心理健康受到影响 :/ ... 老实说,我看到了这个链接,但最后没想去读它...你也需要多次阅读才能掌握绘画的循环,这并不是非常容易的事情...感谢您 ;) ... 对于不透明度,我注意到了它,我也注意到了所有创建新堆叠上下文的属性,例如变换等。 - Temani Afif
好的,所以在这一切中主要的关键词是 [ 对于所有它的流入...] 在 4.1 中当我第一次阅读时,我理解为对于每个子项,我们都会循环但实际上并不是这样...顺便说一句,我知道这是规格说明,但为什么做出这个决定的想法? 我也知道我提供的示例代码很糟糕,因此在理论上很难出现这种情况,因此我们不能抱怨绘画过程。 - Temani Afif
是的,请注意这是一个非常有限的情况:内部流动,未定位,未转换,未浮动,没有不透明度... 我相信这旨在提供一种特殊情况,即您想要一种平面显示,其中几个框形成背景,文本覆盖在所有内容上。但这只是我的猜测。 - vals
我已经添加了一个片段,展示(或者至少试图展示)绘制顺序中的不同步骤,特别是3、4、5和部分7。 - vals
我认为经过很多思考和搜索,我找到了一个非常好的用例 :) 我想这个可以很好地解释这种行为,你可以查看我的答案 ;) - Temani Afif
显示剩余4条评论

10

回答这个问题的人并不是每个人都会。因为我们都已经固定地认为,这是一种可以提高用户体验的东西,是一种直观的东西。有没有人想过,这可能是为了任何CPU处理的好处?

浏览器渲染引擎不会完全绘制一个元素,然后继续绘制下一个元素,因为我们有GPU技术。渲染引擎将元素绘制在不同的分层中,其中每个分层都相互堆叠,交给GPU将所有分层光栅化成一个复合层,显示在屏幕上。

Browser rendered layers

那么,这些层是如何创建的呢?

  • 渲染引擎将所有背景和边框绘制在基础层上。
  • 为具有定位属性的元素创建一个新层。该层被堆叠在基础层之上,以供GPU进行光栅化。当元素移动时,渲染引擎只需告诉GPU移动该层,GPU会完成其余工作。CPU免受绘制开销的影响。
  • 为具有不透明度属性的元素创建一个新层。当不透明度发生变化时,GPU进行光栅化工作。
  • 同样地,对于可以导致CPU重复绘制的输入、按钮、画布、视频等所有元素,都会创建一个新的图层,以便将它们传输到GPU。我们节省了大量的CPU处理时间,对吧? :)
  • 拒绝为具有负边距的元素创建任何新层 :( 。这是显而易见的,浏览器无法为每个带有边距的元素发出新层,因为元素太多了。即使它具有负边距,它可能与其他元素重叠,也可能不重叠。确定唯一的方法是查看渲染树。问题在哪里?我们正在努力节省处理时间,查看每个元素的渲染树将破坏这一努力。
  • 为文本元素发出一个新的层。GPU可以更有效地将文本光栅化到背景上,因此为什么要用CPU在基础层上绘制呢?这就是最初的问题。我想现在每个人都能回答了。
为什么文本在一个单独的层上绘制?
  • CPU不需要在背景上绘制文本,CPU很高兴。
  • 当文本颜色或阴影变化时,CPU只绘制文本层,GPU将其栅格化在背景上。
  • 当背景发生变化时,CPU只绘制背景层,GPU在其上绘制文本。
  • 当文本在固定背景上滚动时,不需要绘制,CPU只告诉GPU移动文本层,GPU完成其余操作。
  • 还有很多...

现在让我们来看看由此带来的神奇效果。

painting and rasterizing

  • 情况1:当为第二个div添加相对位置时,它会得到一个新层,这个新层堆叠在基础层和第一个div的文本层之上。
  • 情况2:应用透明度时也会发生同样的事情。
  • 情况3:任何transform样式都会创建一个新层。
  • 情况4:这个比较有趣。margin不会为第二个div创建任何层,它在第一个div绘制后在基础div上绘制,因此在同一层上覆盖第一个div上的文本。第一个div上的文本位于其自己的层上,该层堆叠在基础层之上,因此GPU将文本栅格化在第二个div的背景上。

[来源:developers.google.com]


2
很明显你做了很出色的工作。但是,很抱歉我不认为你的结论是准确的。解释我为什么不同意会太长,而且主要基于个人观点,所以我认为这样做没有价值...无论如何,我会给你的回答点赞,因为它展示了你所做的工作量。 - vals
只是指出有争议的结论将有助于进一步的研究 :) - Munim Munna
你的回答中的源代码是否解释了你所解释的内容?我认为没有,但可能是我忽略了。非常感谢您清晰地解释了CPU和GPU之间的交互,谢谢! - Ritesh Jagga
哦,我的天啊,“will-change: transform”是创建新的层叠上下文的一个非常棒的方式!这也带来了一个问题:为什么我们还没有本地的方法告诉浏览器创建新的层叠上下文呢? 以前,我使用奇怪的position组合,但这使得生活更加困难。will-change来拯救! - Qwerty
这是一个被低估的答案!我一直在试图记住创建堆叠上下文的所有方法,但我无法弄清楚为什么opacity是其中之一。从这个角度来看,它变得非常合理。现在它完全直观,不需要记忆! - Qwerty
1
隔离(isolate)不是你要找的属性吗? - fweth

6
这是因为层次结构...我将尝试更详细地解释一下...

body {
  margin: 0;
  background: pink;
  color: #fff;
}

.box {
  margin-top: 20px;
  background: red;
}

.bottom {
  margin-top:-10px;
  text-align: right;
  background: green;
}
<div class="box">
  some content
</div>
<div class="bottom">
  other content
</div>

就像你的例子一样,我们的层次结构看起来像这样:

.box
    .box content
.bottom
    .bottom content

所以,如果您现在不传递position: relative,那么它将使用HTML的正常层次结构而不检查divs...

您已经在.box.bottom中实现了背景,因此在这种情况下,当您在.bottom中添加margin-top时,会发生以下情况:

  • .bottom.box具有相同的水平层次位置,但.bottom具有更大的垂直层次,因此将重叠.box的背景
  • .bottom content.box content的位置比.bottom.box更高,因此它们将彼此重叠
  • .bottom content将由于更大的垂直层次而覆盖.box content

是的,在“我的观点”部分,这就是我理解的 :) 但我在哪里可以阅读相关信息呢?有官方规范的链接吗? - Temani Afif
我认为你不会找到最好的官方规范,因为这是HTML层次结构的结果...你只能阅读类似于这样的内容:http://webreference.com/html/rendering/2.html - Mateusz Pęczkowski
是的...我没想过...从来没有!:D 我会搜索,但如果你找到了什么,请分享你的答案 :) 我也会去做它 ;)非常好的问题:D - Mateusz Pęczkowski
我猜我们得到了答案 ;) 检查另一个...它是规范,有一些小关键词会产生差异 :) 如果你快速阅读它,你不会认为会发生这样的事情。 - Temani Afif
耶啊啊...完全是奇怪的东西 ;) - Mateusz Pęczkowski
显示剩余2条评论

3
一种提问的方式是:是否可以以不同的方式处理,仍然满足CSS所需的不同特性,尤其是float属性?
规范指出,对于堆叠上下文(基本上是DOM树中定位的某个部分的顶部块),您按以下顺序绘制其中的元素:
2. 堆叠上下文的顶部元素的背景 3. z-index为负数的元素
到目前为止都很有意义,然后您有
4. 树中顶部元素下的所有块级元素的所有背景和边框(基本上是display: block但未定位的元素)。 5. 然后是树下所有浮动元素的所有背景和边框。 6. 这个步骤与步骤2无关,因此不会干扰这个特定情况。 7. 然后是树下所有非浮动元素的所有内容(或非浮动元素)。 (在第7步中呈现的不仅仅是文本,而是所有内联元素。如果您的内联元素具有背景,则会掩盖其后面的内容)。
这样做的问题在于,流入元素的渲染顺序不是树的顺序。树中较低的元素的背景可能会在树中较高的流入元素之前呈现。问题中暗示的是我们希望得到更像这样的结果:
  1. 按树的顺序渲染所有块级元素的所有背景、边框和流入元素。
这样可以以更直观的方式生成元素。那么为什么要将流入元素与其他元素分开呢?为什么步骤5在步骤7之前?很明显,如果你这样做,那么你就会在浮动元素上出现问题。它们必须在其余流之前放置,因为它们被视为取出流的元素。所以步骤5是有意义的,你需要在考虑非浮动元素之前考虑浮动元素。
那么如果它们像这样在步骤4中呈现:
  1. 按树的顺序渲染所有块级元素的所有背景和边框,然后是浮动元素,最后是非浮动元素。
你仍然会遇到问题,因为浮动元素的预期不同。看看这个片段:

body {
  margin: 0;
  background: pink;
  color: #fff;
}

.box {
  margin-top: 20px;
  background: red;
}

.bottom {
  margin-top:-10px;
  text-align: left;
  background: green;
  
}
<div class="box">
  <span>some content some content some content some content some content some content some content some content some content some content</span>
<span style="float: left; background: navy">
  floated content box<br>
  floated content box<br>
  floated content box<br>
  floated content box
  </span>
  
 
  
  
</div>
<div class="bottom">
  <span style="background-color:turquoise;">other content</span>
  <span style="float: left; background-color:bisque;">
  floated content bottom<br>
  floated content bottom<br>
  floated content bottom
  </span>
  
 
  
</div>

你会发现浮动元素对块级元素的高度没有任何影响,这是预期的,否则结果会很奇怪,与浮动元素的预期效果完全不同。所以,如果上部块中的浮动元素在下部元素的背景之前呈现,那么背景就会覆盖浮动元素。因此,在树顺序中先呈现背景、然后是浮动元素和内联元素也行不通。你需要在到达正常流之前放置所有树的浮动元素。
因此,你几乎无法摆脱这种处理渲染的方式,这意味着你必须在一个上下文中检查所有元素以定位浮动元素,然后定位其余的正常流元素。它有这个奇怪的副作用,但考虑到CSS规范所期望的不同定位的复杂性,我不确定还有其他方法来解决它。
编辑:
我认为这种行为在规范中已经得到了明确的指定,请参见这里: https://www.w3.org/TR/CSS2/visuren.html#floats 浮动元素的内容堆叠,就好像浮动元素生成新的堆叠上下文一样,除了任何定位元素和实际创建新的堆叠上下文的元素参与浮动元素的父级堆叠上下文。浮动元素可以重叠正常流中的其他框(例如,当与浮动元素相邻的正常流框具有负边距时)。当发生这种情况时,浮动元素在非定位内联块的前面呈现,但在内联流块后面呈现。这意味着浮动元素预期会重叠正常流块,并在此类背景前呈现。

好观点,但我只同意50% :) 因为这里浮点数的问题是溢出,所以如果规范像我想要的那样,它将被底部元素隐藏,我会首先找到这个逻辑上合理的地方,因为我们有一个问题,即溢出,我们需要通过正确清除浮点来解决它。我同意50%,因为你的答案几乎与我的结论相同。在这里,您隐含地得出结论,我们可能会面临溢出(无论是通过浮点还是文本变大),更重要的是显示内容在背景之上而不是相反。 - Temani Afif
你的答案和我的(https://dev59.com/DlYM5IYBdhLWcg3whAeH#48895817)之间的区别在于,像这样的东西在开发阶段是可见的,因此如果规范符合我的要求并且浮点数被隐藏了,我们可以看到这一点,并通过进行必要的更改来纠正代码,这就是为什么我不完全同意你的观点,因为开发人员应该意识到结果并进行调整。但在我的答案中,我们可能会面临CSS在客户端上更改以创建溢出的情况;因此,我们应该优先考虑内容。当然,这只是个人结论 :) - Temani Afif
@TemaniAfif 请看我的编辑,我认为这种行为在CSS规范中是明确期望的,这是预期的行为,因此渲染指南对我来说似乎是实现规范的唯一方式(或者至少是最直接的方式)。但是,是的,所有这些都是推测,可能还有更多。这只是一种不同的方法,试图理解这种行为。 - Julien Grégoire
是的,我知道在规格说明中这是明确预期的 :) 这也是我所说的:我们面对一些我们不期望的事情,然后我们在规格说明中阅读到它们,给出了正确的预期方式。当我阅读规格说明时,这对我来说是很清楚的,但我的真正问题是为什么他们会这样决定?所以是的,在规格说明中所有这些行为都被很好地解释了,而且都是合乎逻辑和正常的,但有时我们可能会问“为什么他们决定这样做?”“他们的原因是什么?” - Temani Afif

2
@vals的回答强调了规范中解释了这种行为,但只提供了80%的答案,因为我仍在寻找“为什么?”。由于这种行为有点违反直觉,我试图找到真实的用例,以确定为什么会出现这种行为,而不是像我预期的那样。
经过大量搜索,我得出了一个“合乎逻辑”的结论:优秀的Web开发人员应该了解规范中指定的任何内容,并且不应该让随机/意外的行为留下任何空间,特别是当涉及到规范明确说明的行为而不是浏览器特定行为时。
所以我们编写代码,面对一些“奇怪”的事情,我们学习它们,我们调整我们的代码……直到我们有了符合预期的东西。
由于Web开发人员完全控制自己的开发,我在想是否有任何“外部”工具可能会影响他的CSS和网页呈现,而他无法控制?
是的,其中之一与“可访问性”有关。我不是在谈论Web开发人员应该遵循的指南,而是在谈论某些网站中的小部件,允许您增加字体大小,更改对比度等,以帮助您更好地阅读内容。这种小部件可以使用附加组件在任何地方集成。
这里是一个简化的示例,用户可以增加字体大小,在这种情况下,“上述行为是有用的”,因为它将保持文本内容以上,因此我们可以轻松地阅读它:

$('button').click(function() {
   $('body').css('font-size','22px');
})
body {
 font-size:14px;
 max-width:500px;
}
section {
  height: 80px;
  background: red;
  padding:5px;
  border-top: 40px solid blue;
  color:#fff;
}
div {
  height:80px;
  background:url(https://lorempixel.com/g/400/400/) center/cover;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Make font bigger</button>
<section>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam cursus posuere dolor vel faucibus. Proin augue orci, tempor cursus erat aliquet, pellentesque suscipit odio. Sed eleifend diam in justo vehicula feugiat. In pretium, elit eu dapibus efficitur,
</section>
<section>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam cursus posuere dolor vel faucibus. Proin augue orci, tempor cursus erat aliquet, pellentesque suscipit odio. Sed eleifend diam in justo vehicula feugiat. In pretium, elit eu dapibus efficitur,
</section>
<div>
</div>

在这段代码中,开发者使用了字体大小等于14px,这可能对一些人来说不易阅读,因此增加字体大小是合理的。如果我们这样做,我们将会得到奇怪的行为,但如果不是这样的话,内容将被隐藏,因此我们无法再阅读它!
这种情况给出了这样的决定的充分理由,正如我在问题中所说的:在这种情况下,内容比样式更重要,特别是当涉及到改变初始行为的外部工具时。
这里增加字体大小的意图是突出内容,而不是背景或边框,这证实了绘画顺序应该是这样的,以满足这个要求。

1
有趣的观点...是的,这可能是原因。但是,当然,除非你碰巧在当时与w3c小组的人交谈,否则很难确定。 - vals
@vals 是的,没错,但我至少找到了一个真实的案例,如果内容被隐藏,我会感到惊讶 ;) - Temani Afif
@vals,所以开发人员必须足够愚蠢,为各个部分设置固定的80px高度,并且足够聪明,在各个部分之间留下40px的边距,以便溢出的文本可以显示而不会移动到下一个部分,我想知道有多少人最终会这样做。如果没有边距,后来绘制文本是否有用?我认为规范甚至没有考虑到这些罕见情况来方便使用。此外,开发人员不应该留下随机/意外行为的空间,特别是当涉及到常见/通用行为而不是特定于浏览器的行为时 - Munim Munna
@MunimMunna 嗯,我认为Temani的观点更多地涉及通常留下的边距,以使页面看起来整洁,而不是考虑这种情况时留下的边距。但是,正如我之前所说,了解w3c在编写标准时的真正想法主要是基于个人观点,并且很难证明。 - vals
@vals 是的,这是基于个人观点的,但我想说的是,如果没有留白,那么稍后再绘制文本就没有任何好处。而且很不可能w3c编写规范来促进这种极为罕见的情况,即稍后绘制文本能够完美地解决问题。但谁知道呢! - Munim Munna

0
理解为什么 ? 是关于了解浏览器绘制层的问题。
昨天我问了同样的问题,并寻求为什么?
对我的问题的第一个假设是:
存在重叠。
但是,我发现实际上根本没有重叠,即使在视觉上我们感觉到有重叠!!
这更好地称为相交。
当我阅读关于 z-index 的这个表格时,我开始转变我的想法,认为这是相交的时刻。
**Layer**           **Description**
Bottom layer    Farthest from the observer
Layer -X        Layers with negative z-index values
Layer 0         Default rendering layer
Layer X         Layers with positive z-index values
Top layer       Closest to the observer

事实上没有新的堆叠上下文,这意味着元素已经被绘制在同一层上(即第0层),这意味着它们相交而不是重叠,这是关键点。
浏览器想要先完成所有背景吗?因为它知道:
  • 它们在同一层上
  • 它们是要先绘制的东西,然后再绘制文本

-1
发生的情况是,您有两个重叠的“框”,需要在同一z层,即图层0上呈现。然而,在CSS基本框模型入门中,解释了边框区域,它说:

当框上设置了背景(background-colorbackground-image)时,它会延伸到边框的外缘(即在z排序中在边框下方延伸)。

我认为边框和内容都在“前景”中。
因此,绘制所有框在同一图层上的规范,再加上将背景绘制在前景下面的规范,我想结果是将所有背景绘制在所有前景下面。
在每个“子层”内,重叠是根据HTML顺序进行的。
要理解为什么文章中的DIV在同一层上,需要阅读堆叠上下文
要“理解”为什么背景在前景下面,需要阅读CSS基本框模型介绍

我尝试了每一种方法,但它们似乎都不是正确的方向。我需要理解发生了什么,所以我大部分时间都在阅读 MDN。一旦我理解了这三个 DIV 需要在同一层上,我就明白了这篇文章中发生了什么。 - edixon
要理解为什么这3个DIV在同一层上,应该阅读堆叠上下文 - edixon
首先只有两个 Div,第一个答案已经提供了所有的细节,所以我不确定您是否已经阅读了它并且还阅读了其他细节。而主要问题是“为什么?”这种行为,我们已经有了解释。 - Temani Afif

-1

需要注意的是,在这种情况下,每个 div 的高度都由其内容确定。假设结果高度为 20px。

那么,如果你说第一个 div 的 margin-top: 20px,第二个 div 在第一个 div 之后声明,从第一个 div 结束的地方开始。

因此,第二个 div 的初始位置将是第一个 div 的 margin-top 加上第一个 div 的高度。假设这个值为 40px。

因此,对于这种情况,第二个 div 的起始位置将为 40px。当你说第二个 div 的 margin-top 是 -15px 时,初始位置将为 40px-15px。

因此,如果你想让第二个 div 重叠在第一个 div 上面,你应该将 margin-top 设置为第一个 div 高度的负数。


你明白这个问题是关于什么的吗? - Temani Afif
哇..实际上是这样,但你明确表示你不是在寻找像position: relative这样的答案,而那就是你看到的行为。澄清一下:所有元素都具有默认值的CSS属性。你知道这一点,对吧?属性position的默认值为static。这就是你在那里看到的。你可以在这里阅读一些相关内容。因此,如果您希望元素相对于其他元素采用相对位置,则使用position relative。请在此处阅读更多信息: 链接 - Lisandro Gelder
好的,所以你没有理解问题 :) ... 我知道关于位置和所有不同值的一切,我知道如何使用相对位置和所有的东西,嗯,我对CSS非常了解 ;) .... 但是请仔细阅读问题,我想要了解我看到的行为在哪里被指定[vals的答案回答了这个问题],然后我想知道为什么会有这种行为决策... 请仔细阅读问题、评论和所有答案再回答。 - Temani Afif

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