html - 为什么内容没有被重叠元素的背景覆盖?

标签 html css background overlap

情况如下:

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 重叠。我期望看到一个完全重叠另一个,但事实并非如此。第二个 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 有一些棘手的事情,当我们第一次面对它们时,我们不会怀疑它们(例如边距折叠、从 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 来决定堆叠。我希望了解为什么会发生这样的事情。

最佳答案

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

The painting order for the descendants of an element generating a stacking context (see the z-index property) is:

  1. If the element is a root element:
    1. background color of element over the entire canvas.
    2. background image of element, over the entire canvas, anchored at the origin that would be used if it was painted for the root element.
  2. If the element is
    • a block, list-item, or other block equivalent:
      1. background color of element unless it is the root element.
      2. background image of element unless it is the root element.
      3. column rule of the element.
      4. border of element.
    • Otherwise, if the element is a block-level table:
      1. table backgrounds (color then image) unless it is the root element.
      2. column group backgrounds (color then image).
      3. column backgrounds (color then image).
      4. row group backgrounds (color then image).
      5. row backgrounds (color then image).
      6. cell backgrounds (color then image).
      7. cell column rule for multi-column.
      8. all table borders (in tree order for separated borders).
  3. Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.
  4. For all its in-flow, non-positioned, block-level descendants in tree order:
    • If the element is a block, list-item, or other block equivalent:
      1. background color of element.
      2. background image of element.
      3. column rule of the element.
      4. border of element.
    • Otherwise, the element is a table:
      1. table backgrounds (color then image).
      2. column group backgrounds (color then image).
      3. column backgrounds (color then image).
      4. row group backgrounds (color then image).
      5. row backgrounds (color then image).
      6. cell backgrounds (color then image).
      7. cell column rule (multi-column).
      8. all table borders (in tree order for separated borders).
  5. All non-positioned floating descendants, in tree order. For each one of these, treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context are considered part of the parent stacking context, not this new one.
  6. If the element is an inline element that generates a stacking context, then:
    1. For each line box that the element is in:
      1. Jump to 7.2.1 for the box(es) of the element in that line box (in tree order).
  7. Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:

    1. If the element is a block-level replaced element, then: the replaced content, atomically.
    2. Otherwise, for each line box of that element:

      1. For each box that is a child of that element, in that line box, in tree order:

        1. background color of element.
        2. background image of element.
        3. column rule of the element.
        4. border of element.
        5. For inline elements:
          1. For all the elements in-flow, non-positioned, inline-level children that are in this line box, and all runs of text inside the element that is on this line box, in tree order:
            1. If this is a run of text, then:
              1. any underlining affecting the text of the element, in tree order of the elements applying the underlining (such that the deepest element’s underlining, if any, is painted topmost and the root element’s underlining, if any, is drawn bottommost).
              2. any overlining affecting the text of the element, in tree order of the elements applying the overlining (such that the deepest element’s overlining, if any, is painted topmost and the root element’s overlining, if any, is drawn bottommost).
              3. the text
              4. any line-through affecting the text of the element, in tree order of the elements applying the line-through (such that the deepest element’s line-through, if any, is painted topmost and the root element’s line-through, if any, is drawn bottommost).
            2. Otherwise, jump to 7.2.1 for that element
        6. For inline-block and inline-table elements:
          1. For each one of these, treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context are considered part of the parent stacking context, not this new one.
        7. For inline-level replaced elements:
          1. the replaced content, atomically.
        8. Optionally, the outline of the element (see 10 below).

        Note, some of the boxes may have been generated by line splitting or the Unicode bidirectional algorithm.

    3. 可选地,如果元素是 block 级的,则元素的轮廓(参见下面的 10)。

  8. 所有定位、不透明度或变换后代,按树顺序分为以下类别:

    1. 所有使用“z-index: auto”或“z-index: 0”定位的后代,按树顺序排列。对于那些具有“z-index:auto”的元素,将元素视为 它创建了一个新的堆叠上下文,但任何定位的后代和 实际创建新堆栈上下文的后代应该是 被视为父堆叠上下文的一部分,而不是这个新的。为了 那些带有 'z-index: 0' 的处理生成的堆叠上下文 原子地。

    2. 所有不透明度小于 1 的不透明度后代,按树顺序,创建一个原子生成的堆叠上下文。

    3. 除无变换之外的所有具有变换的变换后代,按树顺序,创建一个自动生成的堆叠上下文。
  9. 由 z 索引大于或等于 1 的定位后代形成的堆叠上下文,按 z 索引顺序(最小的在前),然后是树 订单。

现在说真的,请参阅the w3c paint order documentation

第4.1点,绘制了 child 的背景

在第 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 之后、setp 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>

关于html - 为什么内容没有被重叠元素的背景覆盖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48731110/

相关文章:

css - 视网膜手持显示器 : Can a 1px border be achieved via CSS?

html - 为什么在我使用 Chrome 开发人员工具强制元素状态之前,我的表格单元格(偶尔)不会表现出 'hover' 行为?

listview - 点击时更改 ListView 行背景

Android - 没有边距的背景图片

html - 应用不透明度时如何在 IE7 中删除按钮周围的黑色边框

javascript - Slick carousel centerMode 的问题 - 不断增长的中心元素

html - Safari 浏览器问题 : Fixed footer is hiding the bottom part of my content

javascript - 将单元格值从表格复制到文本框

css - 数字标牌系统中的网站背景全屏

ios - 如何进行代码后台下载?