为什么内容没有被重叠元素的背景覆盖? [英] Why the content is not covered by the background of an overlapping element?

查看:56
本文介绍了为什么内容没有被重叠元素的背景覆盖?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是情况:

 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会有一些棘手的东西,我们在初次面对它们时就不会怀疑(例如边距折叠,从主体到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来决定堆栈.希望了解为什么会发生这种情况.

解决方案

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

生成堆叠上下文的元素的后代的绘画顺序为(见z-index属性)

  1. 如果元素是根元素:

    1. 整个画布上元素的背景色.
    2. 元素在整个画布上的背景图像,锚定在为根元素绘制时将使用的原点.

  2. 如果元素是
    • 一个块,列表项或其他等效块:

      1. 元素的背景色,除非它是根元素.
      2. 元素的背景图片,除非它是根元素.
      3. 元素的列规则.
      4. 元素的边界.

    • 否则,如果元素是块级表:

      1. 表背景(先是颜色,然后是图像),除非它是根元素.
      2. 列组背景(先是颜色,然后是图像).
      3. 列背景(先是颜色,然后是图像).
      4. 行组背景(先是颜色,然后是图像).
      5. 行背景(先是颜色,然后是图像).
      6. 单元格背景(先是颜色,然后是图像).
      7. 多列的单元格列规则.
      8. 所有表格边框(以树顺序表示分隔的边框).

  3. 由具有负z索引(不包括0)的按z索引顺序排列的后代所形成的堆叠上下文(首先为负数),然后 树顺序.
  4. 对于所有流入的,未定位的,块级的后代,按树顺序排列:
    • 如果元素是块,列表项或其他等效块:

      1. 元素的背景色.
      2. 元素的背景图片.
      3. 元素的列规则.
      4. 元素的边界.

    • 否则,该元素是一个表:

      1. 表格背景(先是颜色,然后是图像).
      2. 列组背景(先是颜色,然后是图像).
      3. 列背景(先是颜色,然后是图像).
      4. 行组背景(先是颜色,然后是图像).
      5. 行背景(先是颜色,然后是图像).
      6. 单元格背景(先是颜色,然后是图像).
      7. 单元格列规则(多列).
      8. 所有表格边框(以树顺序表示分隔的边框).

  5. 所有未定位的浮动后代,以树顺序.对于其中的每个元素,都应将其视为已创建新堆叠的元素 上下文,但实际上是任何定位的后代和后代 创建一个新的堆栈上下文被认为是父级的一部分 堆栈上下文,而不是这个新上下文.
  6. 如果该元素是生成堆栈上下文的内联元素,则:

    1. 对于元素所在的每个行框:

      1. 跳转到该行框中的元素的框(按树顺序)到7.2.1.

  7. 否则:首先按元素顺序,然后按树顺序为其所有流入的,非定位的,块级后代:

    1. 如果该元素是块级替换的元素,则:原子替换的内容.
    2. 否则,对于该元素的每个行框:

      1. 对于每个作为该元素子级的框,在该行框中,按树顺序:

        1. 元素的背景色.
        2. 元素的背景图片.
        3. 元素的列规则.
        4. 元素的边界.
        5. 对于内联元素:

          1. 对于此行框中的所有流入,未定位,行内子级元素,以及其中的所有文本行, 此线框上的元素,以树顺序:

            1. 如果这是一段文字,则:

              1. 任何影响元素文本的下划线,以应用该下划线的元素的树顺序(使得最深的 元素的下划线(如果有的话)涂在最上面,并且根部 元素的下划线(如果有的话)显示在最底部).
              2. 任何影响元素文本的覆盖,以应用覆盖的元素的树顺序(使得最深的 元素的外框(如果有的话)涂在最上层,并且根 元素的上划线(如果有的话)显示在最底部).
              3. 文字
              4. 影响元素文本的任何直通,以应用直通的元素的树顺序排列(以使最深 元素的直通线(如果有的话)涂在最上面,并且根部 元素的直行(如果有的话)绘制在最底部).

            2. 否则,请跳至该元素的7.2.1

        6. 对于内联块和内联表元素:

          1. 对于这些元素中的每一个,都应将元素视为已创建新的堆叠上下文,但要处理所有定位的后代和后代 实际上创建新堆栈上下文的部分被认为是 父堆栈上下文,而不是这个新堆栈上下文.

        7. 对于内联级别替换的元素:

          1. 被替换的内容,原子地

        8. (可选)元素的轮廓(请参见下面的10).

        请注意,某些方框可能是通过行拆分或Unicode双向算法生成的.

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

  8. 所有树状排列的定位,不透明或转换后代,分为以下类别:

    1. 所有定位的后代,其"z-index:自动"或"z-index:0"以树顺序排列.对于具有"z-index:auto"的用户,将其视为 它创建了一个新的堆栈上下文,但是任何后代和 实际创建新堆栈上下文的后代应该是 被认为是父堆栈上下文的一部分,而不是这个新的上下文.为了 带有"z-index:0"的代码将处理生成的堆栈上下文 原子地.

    2. 所有不透明度小于1的不透明度子代,以树顺序创建原子生成的堆栈上下文.

    3. 所有具有非变换形式的变换后代,以树顺序创建原子生成的堆栈上下文.

  9. 由z索引大于或等于1的定位后代(按最小顺序排列,然后是树)形成的堆叠上下文 订单.

现在,请认真参考 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步之后和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> 

Here is the situation:

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>

What's happening?

As you may see we have two div without any complex styling (simply background-color). I am making the second div to overlap the first one by applying a negative margin-top. I am expecting to see one completely overlapping the other but this is not the case. The second div is sliding between the content and the background of the first one and it's a strange behavior for me.

The animation has nothing to do here, I simply use it to better show the behavior. We can simply add negative margin without animation and we will have the same thing:

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>

So my question is : why such behavior?


By the way, we all know that there is some tricky things with CSS that we don't suspect when we face them the first time (like margin-collapsing, background propagation from body to html, white space issue,etc...) but they are clearly explained somewhere and I hope to find an official resource where I can clearly understand this and not only get something like "Maybe this happen because...", "I suspect this related to...", "I think it have something to do with...",etc.


My opinion/explanation about this

I suppose content like text are more important than background and other visual styling so maybe when we have overlapping we place all the text at the top and all the other styling at the bottom, we decide about the order inside each group and then we print the result.

Here is a more complex example:

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>

We can clearly see that the visual stack is as follow (starting from bottom to top):

  • Styling of the first div(background + border)
  • Styling of the second div(background + border)
  • Styling of the third div(background + border)
  • text content of the first div
  • text content of the second div
  • text content of the third div

Important notice: Before answering, please note that I am not looking for a fix to this or how to avoid this. By simply adding position:relative the behavior disappear and we can play with z-index to decide about stacking. Am looking to understand why such thing happen.

解决方案

WARNING: Reading the following information can affect your mental health.

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. Optionally, if the element is block-level, the outline of the element (see 10 below).

  8. All positioned, opacity or transform descendants, in tree order that fall into the following categories:

    1. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one. For those with 'z-index: 0' treat the stacking context generated atomically.

    2. All opacity descendants with opacity less than 1, in tree order, create a stacking context generated atomically.

    3. All transform descendants with transform other than none, in tree order, create a stacking context generated atomically.

  9. Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.

Now seriously, refer to the w3c paint order documentation

In point 4.1, the background of children is painted

In point 4.4, the border of children is painted.

When point 4 is finished, all background and border of your snippet have been painted

Now, in point 7.2.1.5.1.1.3, the text of the children is painted.

This is the behaviour that you are seeing.

Notice also that is easy to change this behaviour. We can activate point 8.2, (setting opacity) and it will paint like you may have expected:

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>

Another snippet, showing several point in the document:

Notice that all the border and background in step 4 are rendered after step 3, and before setp 5. But the text in step 4 is step 7, so is rendered after text in step 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>

I don't know if this counts as an use case : this more natural the initial behaviour the the one set by the elements positioning relative

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>

这篇关于为什么内容没有被重叠元素的背景覆盖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆