【问题标题】:Collapsed margin in CSSCSS中的折叠边距
【发布时间】:2017-07-09 20:59:00
【问题描述】:

MDN 解释折叠边距here

这些是它解释的基本 3 条规则:

相邻的兄弟姐妹

相邻兄弟的边距被折叠(除了后面的 兄弟姐妹需要清除过去的浮动)。

父母和第一个/最后一个孩子

如果没有边框、内边距、内联内容, block_formatting_context 创建或清除以分隔 块的边缘顶部距其第一个子块的边缘顶部,或 没有边框、填充、内联内容、高度、最小高度或最大高度 将块的 margin-bottom 与它的 margin-bottom 分开 最后一个孩子,那么这些边距就会崩溃。折叠的边距结束 在父母之外。

空块

如果没有边框、内边距、内联内容、高度或最小高度 将块的 margin-top 与其 margin-bottom 分开,然后是其顶部 并且底部边距折叠。

查询a:我需要了解以下示例中按顺序应用的3条规则。

查询b:如果对于空块元素的边距折叠,那么它作为顶部或底部边距出现吗?您可能会说它有什么不同,但是如果我使用下面示例中的轮廓,这里看起来好像它被折叠为顶部。

基本上我有 3 个 <p> 元素,其中中间一个是空的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ex1</title>
    <style>

        body{
            border: 1px solid black;
        }

        p{
            margin-top: 10px;
            margin-bottom: 10px;
            outline: 1px solid black;
        }

        #empty{
            margin: 20px;
        }

    </style>
</head>
<body>
    <p>
        The oldest classical Greek and Latin writing had little or no space between words, and could be written in boustrophedon (alternating directions). Over time, text direction (left to right) became standardized, and word dividers and terminal punctuation became common. The first way to divide sentences into groups was the original paragraphos, similar to an underscore at the beginning of the new group.[3] The Greek paragraphos evolved into the pilcrow (¶), which in English manuscripts in the Middle Ages can be seen inserted inline between sentences. The hedera leaf (e.g. ☙) has also been used in the same way.
    </p>
    <p id ='empty'></p>
    <p>
        The oldest classical Greek and Latin writing had little or no space between words, and could be written in boustrophedon (alternating directions). Over time, text direction (left to right) became standardized, and word dividers and terminal punctuation became common. The first way to divide sentences into groups was the original paragraphos, similar to an underscore at the beginning of the new group.[3] The Greek paragraphos evolved into the pilcrow (¶), which in English manuscripts in the Middle Ages can be seen inserted inline between sentences. The hedera leaf (e.g. ☙) has also been used in the same way.
    </p>
</body>
</html>

请注意,第一段和最后一段之间的最终边距为 20 像素。

【问题讨论】:

    标签: css


    【解决方案1】:

    查询a:我需要了解以下示例中按顺序应用的3条规则。

    只要不为具有不同值的相同选择器多次声明规则,顺序就无关紧要。

    • body 上的边框,将在其内部保留第一个和最后一个子级的垂直边距。

    • 空段落的高度为 0,边距将与前一个和下一个同胞折叠/合并,它会表现得好像它不存在一样。添加 1px 的高度来测试行为:

    见下面的sn-p

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>ex1</title>
        <style>
    
            body{
                border: 1px solid black;
            }
    
            p{
                margin-top: 10px;
                margin-bottom: 10px;
                outline: 1px solid black;
            }
    
            #empty{
                margin: 20px;
                height:1px;
            }
    
        </style>
    </head>
    <body>
        <p>
            The oldest classical Greek and Latin writing had little or no space between words, and could be written in boustrophedon (alternating directions). Over time, text direction (left to right) became standardized, and word dividers and terminal punctuation became common. The first way to divide sentences into groups was the original paragraphos, similar to an underscore at the beginning of the new group.[3] The Greek paragraphos evolved into the pilcrow (¶), which in English manuscripts in the Middle Ages can be seen inserted inline between sentences. The hedera leaf (e.g. ☙) has also been used in the same way.
        </p>
        <p id ='empty'></p>
        <p>
            The oldest classical Greek and Latin writing had little or no space between words, and could be written in boustrophedon (alternating directions). Over time, text direction (left to right) became standardized, and word dividers and terminal punctuation became common. The first way to divide sentences into groups was the original paragraphos, similar to an underscore at the beginning of the new group.[3] The Greek paragraphos evolved into the pilcrow (¶), which in English manuscripts in the Middle Ages can be seen inserted inline between sentences. The hedera leaf (e.g. ☙) has also been used in the same way.
        </p>
    </body>
    </html>

    在我自己的拙见中,如果没有绘制元素(高度 = 0 = null ),那么即使 display 未设置为 none,也不应绘制轮廓。


    查询 b:如果对于空块元素的边距折叠,那么它会作为顶部或底部边距出现吗?您可能会说它有什么不同,但是如果我使用下面示例中的轮廓,这里看起来好像它被折叠为顶部。

    不知何故,高度为 0 并且 没有块格式上下文重置,当元素实际上没有被绘制时,浏览器仍然会尽力绘制这个轮廓。它将从元素所在位置的上边距值绘制轮廓。

    查看下面触发 BFC 的 sn-p

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ex1</title>
      <style>
        body {
          border: 1px solid black;
        }
        
        p {
          margin-top: 10px;
          margin-bottom: 10px;
          outline: 1px solid black;
        }
        
        #empty {
          margin: 20px;
          /* reset BFC  see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context*/
          display: table;
          /* overflow:hidden; resets also the BFC read the link provided to start understands how this works :) */
        }
      </style>
    </head>
    
    <body>
      <p>
        The oldest classical Greek and Latin writing had little or no space between words, and could be written in boustrophedon (alternating directions). Over time, text direction (left to right) became standardized, and word dividers and terminal punctuation
        became common. The first way to divide sentences into groups was the original paragraphos, similar to an underscore at the beginning of the new group.[3] The Greek paragraphos evolved into the pilcrow (¶), which in English manuscripts in the Middle
        Ages can be seen inserted inline between sentences. The hedera leaf (e.g. ☙) has also been used in the same way.
      </p>
      <p id='empty'></p>
      <p>
        The oldest classical Greek and Latin writing had little or no space between words, and could be written in boustrophedon (alternating directions). Over time, text direction (left to right) became standardized, and word dividers and terminal punctuation
        became common. The first way to divide sentences into groups was the original paragraphos, similar to an underscore at the beginning of the new group.[3] The Greek paragraphos evolved into the pilcrow (¶), which in English manuscripts in the Middle
        Ages can be seen inserted inline between sentences. The hedera leaf (e.g. ☙) has also been used in the same way.
      </p>
    </body>
    
    </html>

    【讨论】:

    • 为什么你认为一个高度为零的元素是“未绘制”,即使它的显示不是none?
    • @BoltClock 因为它不使用空间并且平坦到 0(在其后面放置任何单位,添加任何背景颜色)它只是没有被绘制,因为没有什么可以绘制 :) 。当它是一个块时,您甚至不必处理行高。我还提到了行为不同的块形成上下文。 (请参阅显示测试:表或溢出;隐藏在顶部/底部边距的位置。有些东西与我的观点不一致。或者在触发 bfc 以及未触发或根本不触发时绘制边距 :) 它是我认为这是一个有趣的妥协。
    • 我猜你说的是空元素——因为如果元素不是空的,那么不绘制它就意味着它的任何内容,包括绝对定位的元素,都不会被渲染。 (请注意,如果流中没有任何后代元素,非空元素的边距仍然可以折叠 - 因此我的答案中引用的最后一句话。)
    • @BoltClock 我只讨论了显示为 block 的空元素,这里

      涉及问题,而 id="empty" 用于在测试中进行选择。 BFC 与否,行为不同,我同意 BFC 行为(空块)没有问题,因为看起来是连贯的,只有当没有 BFC 时才会显得奇怪......并且只因为轮廓而看到; )

    • @BoltClock 如果您提到在空块元素上触发 BFC 时的不同行为(在这种情况下呈现顶部和底部边距),我会删除我的答案,我的英语太糟糕了清除:)
    【解决方案2】:

    #empty 的边距折叠通过,产生 20px 的折叠通过边距。此折叠边距与第一段的 10px 底部边距和最后一段的 10px 顶部边距一起折叠。这会导致第一段和最后一段之间有 20px 的间隙,因为折叠后的边距大于它们的任何一个边距,因此会将它们都吞没。

    您的观察是正确的:#empty,当它折叠通过时,会以其顶部边距呈现。来自spec

    • [...] 元素上边框边缘的位置与元素具有非零下边框时的位置相同。

    请注意,被折叠的元素的位置不会影响被折叠的其他元素的位置;只有在布置这些元素的后代时才需要顶部边框边缘位置。

    “如果元素具有非零底部边框”的位置是元素的位置,如果元素的边距没有塌陷,因为具有非零底部边框阻止边距折叠。

    【讨论】:

    • 您指定的步骤顺序是唯一的解决方案吗?
    • @Breaking Benjamin:“步骤顺序”是什么意思,“解决方案”是什么意思?我不认为您要在这里解决问题。
    • 您提到了如何将规则应用于折叠边距。你在那里按顺序回答。例如:第 1 步:#empty 的边距折叠通过,产生 20px 的折叠边距。第 2 步:此折叠边距与第一段的 10px 底部边距和最后一段的 10px 顶部边距一起折叠。我在问这些步骤顺序是唯一的方法还是计算它的可能方法之一。我有一种或多种方法来实现最终的 20px 。我想知道,将来这些步骤的顺序是否重要?我所说的步骤是指这 3 条基本规则。
    • @Breaking Benjamin:您也可以说,#empty 的每个 20px 边距在塌陷之前都会吞噬其相邻的 10px 边距,您仍然会得到相同的结果。所以顺序并不重要。