【问题标题】:margin-top not working with clear: bothmargin-top 不适用于 clear: both
【发布时间】:2011-05-11 00:59:40
【问题描述】:

<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both; margin-top: 200px;">Main Data</div>

为什么“主数据”的margin:top 在上面的代码中不起作用?

【问题讨论】:

  • 您使用的是哪个浏览器?我也使用 Firefox 和 IE 以及 chrome 检查了它。
  • 这里的大多数答案都为这种行为提供了解决方法,这很好,但如果你想要一个(长而难的)答案,它实际上解释了 为什么 它发生在第一个地点,见mine
  • 大多数答案都说“如何”而不是“为什么”!

标签: css css-float


【解决方案1】:

您可以将两个浮动 div 放入 另一个 设置“溢出:隐藏”的 div:

<div style='overflow:hidden'>
  <div style="float: left;">Left</div>
  <div style="float: right;">Right</div>
</div>
<div style="clear: both; margin-top: 200px;">Main Data</div>

edit — 为这个 5 年前的答案补充一点:我认为造成这种混乱行为的原因是 margin collapse 的过程有些复杂。使用 OP 的原始 HTML 的一个好技巧是添加这样的 CSS 规则:

div { border: 1px solid transparent; }

噗!现在(没有我的额外&lt;div&gt;)它工作正常!好吧,除了边界上的那个额外像素。特别是,我认为这是clear: both 的工作方式和导致 OP 中代码出现意外布局的边距折叠规则的结合。

再次编辑 — 有关完整(而且我认为完全准确)的故事,请参阅 Mark Amery's excellent answer。这个答案掩盖了细节有一些复杂性。

【讨论】:

  • 能否详细说明一下?
  • @user395881 浏览器执行的边距计算与位于相同布局上下文中的元素有关。对于浮动元素,边距是相对于其他本地浮动元素和(我认为)内联内容计算的。但是这些静态块元素处于不同的上下文中。我同意布局规则复杂且难以理解。 W3C 文档中有一些图表可以解释一些东西。
  • 浮动元素实际上不“存在”显然是不正确的,因为它解释了边距不起作用。如果这就是它的全部内容,那么我们会期望看到已清除 div 的边距框的顶部从父元素的顶部开始,而不是从浮动元素的底部开始。相反,我们看到边距没有生效根本; OP 原始代码中已清除的 div 最终定位 higher 比浮动 div 的 actually 不存在。您的解决方案有效,但您对问题原因的解释不可能是正确的。
  • @MarkAmery 我真的不确定我明白你在说什么。
  • @Pointy 在给定 OP 代码的情况下,带有 margin-top 的 div 的位置与删除浮动 div 或给定 position:absolute 时的位置不同。这意味着效果不能归结为浮动的 div 并不是真正“存在”以用于保证金计算。
【解决方案2】:

虽然 Pointy 展示了如何将浮点数包装在 div 中,但您也可以在浮点数和主数据部分之间插入一个空 div。例如:

<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both;"></div>
<div style="margin-top: 200px;">Main Data</div>

这在不希望在某些 HTML 周围添加 div 包装器的情况下可能很有用。

【讨论】:

  • 这是一个非常聪明的方法。您还可以将 ~
    ~ 的高度设置为 ~margin-top~ 您将给出主要数据 ~
    ~
【解决方案3】:

规范背后的逻辑令人费解,涉及clearancecollapsing margins 规则的复杂交互。

您可能熟悉传统的 CSS box model,其中 内容框 包含在 边框框内的 填充框 中 包含在 边距框

对于将clear 设置为none 以外的元素的元素,可能会在此模型中引入一个附加组件:clearance

“none”以外的值可能会引入clearance。 Clearance 会抑制边距折叠并充当元素顶部边距上方的间距。

换句话说,这些情况下的盒子模型看起来更像这样:

但是什么时候引入许可,应该有多大?让我们从第一个问题开始。规范says:

计算设置了 'clear' 的元素的间隙是通过首先确定元素上边框边缘的假设位置来完成的。如果元素的“clear”属性为“none”,则该位置是实际上边框边缘所在的位置。

如果元素上边框边缘的这个假设位置没有超过相关的浮动,则引入间隙,并根据 8.3.1 中的规则折叠边距。

让我们将此逻辑应用于提问者的代码。请记住,我们试图在下面的代码中解释第三个 div 的位置(添加背景以帮助可视化):

<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: both; margin-top: 200px; background: blue;">Main Data</div>

让我们想象一下,正如规范要求的那样,clear 在第三个 div 上设置为 none,而不是 both。那么上面的 sn-p 会是什么样子呢?

<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: none; margin-top: 200px; background: blue;">Main Data</div>

这里,第三个 div 重叠两个浮动 div。可是等等;为什么会这样?当然,浮动元素与块级元素重叠是允许的(根据Floats spec“由于浮动不在流中,因此在浮动框之前和之后创建的非定位块框垂直流动,就好像浮动不存在。”),但我们的第三个 div 上面有 margin-top 的负载,并且位于两个浮动 div 之后;两个浮动的 div 不应该出现在 body 的顶部,而第三个 div 不应该出现在 200px 下方,远低于它们吗?

没有发生这种情况的原因是第三个 div 的边距折叠到 div 父级的边距(在本例中为主体 - 但如果将所有三个 div 包装在父级 div 中,也会发生相同的行为)。 Collapsing margins spec(以下引用,省略了几个不相关的细节)告诉我们:

相邻的垂直边距折叠...

两个边距相邻当且仅当:

  • 两者都属于参与相同块格式化上下文的流内块级框
  • 没有线框,没有间隙,没有填充,没有边框将它们分开......
  • 两者都属于垂直相邻的框边,即形成以下对之一:
    • 框的上边距及其第一个流入子元素的上边距
    • ...

我们示例中的第三个 div 肯定不是 body 的 第一个孩子,但它是它的第一个 in-flow 孩子。请注意,根据https://www.w3.org/TR/CSS22/visuren.html#positioning-scheme:

一个元素被称为out of flow,如果它是浮动的、绝对定位的或者是根元素。如果元素不是外流,则称为 in-flow

由于我们示例中的第一个和第二个 div 是浮动的,因此只有第三个 div 是流入的。因此,它的上边距与其父级的上边距相邻,并且边距折叠 - 向下推整个主体,包括两个浮动元素。因此,尽管margin-top 很大,但第三个 div 与其兄弟姐妹重叠。因此 - 在这个假设的情况下,第三个元素的 clear 设置为 none - 我们满足以下条件:

元素的上边框没有超过相关的浮动

因此:

引入清除,边距按照 8.3.1 中的规则折叠

清仓多少?该规范为浏览器提供了两种选择,并附有一些澄清说明:

然后将清除量设置为以下两者中的较大者:

  • 放置块的边界边缘所需的量,即使是要清除的最低浮动的底部外边缘。
  • 将块的顶部边框边缘放置在其假设位置所需的数量。

或者,间隙精确设置为放置块边界边缘所需的量,即使要清除的最低浮动的底部外边缘也是如此。

注意:这两种行为都允许等待评估其与现有 Web 内容的兼容性。未来的 CSS 规范将需要其中之一。

注意:间隙可以是负数或零。

在我们开始应用这些规则之前,我们立即遇到了难题。还记得在clearnone假设 情况下我们必须考虑的折叠边距吗?嗯,它存在于我们正在计算要使用的许可的这种非假设案例中,因为许可的存在会抑制它。回想一下前面引用的 collapsing margin rules from 8.3.1,它规定边距仅在以下情况下相邻

  • 没有线框,没有间隙,没有内边距和边框将它们分开

(强调添加)。因此,第三个 div 的上边距和其父级的上边距不再相邻。我们可以在我们的示例 sn-p 中模拟这种预清除场景,方法是保留 clear: none,但将 padding-top: 1px 添加到正文中,这也禁用了边距折叠,根据上面引用的规则。

body {
  padding-top: 1px;
}
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: none; margin-top: 200px; background: blue;">Main Data</div>

现在,与边距折叠时不同,我们的第三个 div 舒适地低于它的两个浮动兄弟。但是我们已经决定,基于边距确实崩溃的假设场景,必须添加间隙;剩下的就是选择清仓的数量,以便:

将块的边框边缘与要清除的最低浮动的底部外边缘对齐

所以我们别无选择,只能对第三个 div 应用 间隙,以便将其顶部 边界边缘 向上拖动以接触底部 其上方浮动元素的外边缘(也称为margin edge)。因此,如果浮动元素的高度均为 10px,并且第三个 div 的上边距为 200px,则将应用 -190px 的间隙。最后,我们得到了提问者看到的最终结果:

<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: both; margin-top: 200px; background: blue;">Main Data</div>

(请注意,如果您使用浏览器的开发工具检查上面 sn-p 中的第三个 div,您仍然可以看到 div 上方 200px 的上边距,超出所有其余内容- 只是整个边距框都被大的负间隙向上拖了。)

简单!

【讨论】:

  • 这 - 好吧,我想说“有道理”,但那不太对 - 当然是准确的故事。我想我在没有做任何工作的情况下得出的结论是,没有办法引入没有布局影响的“边缘崩溃围栏”(0px“厚度”)。对吗?
  • @Pointy 对于容器/子崩溃的情况,父容器上的overflow: autooverflow: hidden 应该可以解决问题,根据规范中的大 Note w3.org/TR/CSS22/box.html#collapsing-margins 以及像stackoverflow.com/a/6204990/1709587 这样的流行答案(尽管由于某种原因,如果容器是body 元素,它就不起作用)。我不太确定为什么会这样,因为它取决于“块格式化上下文”的定义(我没有研究过,目前也不理解)。
  • @Pointy 使用例如栅栏0.02px 似乎也能正常工作(至少在 Chrome 中 - 可能是特定于浏览器的),尽管对布局没有明显影响。但是,像 0.01px 这样的较小的栅栏不起作用。为什么?不知道。
  • 是的,我有一半记得在处理我自己版本的这个问题时尝试越来越小的边框宽度(等),直到我厌倦了它并决定我并不真正关心那么多.这当然是一组令人惊讶的行为。
  • 来自规范:“建立新块格式化上下文的元素的边距(例如浮动和具有'overflow'而不是'visible'的元素)不会与它们的流入子代一起折叠。”至于为什么这样做(就像从 CSS2 到 CSS2.1 的许多其他与 BFC 相关的更改一样),我不确定,但 I made an educated guess。它似乎不适用于 body 元素的原因是因为the body element loses its overflow property to html when html has overflow: visible
【解决方案4】:

Pointy 和 Randall Cook 给出了很好的答案。我想我会再展示一个解决方案。

<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="float: left; clear: both; margin-top: 200px;">Main Data</div>

如果您将第三个元素设为“float: left;” AND “clear: both;”,它应该具有为第 3 个元素提供 200 像素边距的预期效果。这是一个link 的示例。

这也可能会影响其他后续元素是否需要浮动。但是,它也可能具有预期的效果。

【讨论】:

  • 第三个 div 后面的元素搞砸了。最后必须清除浮动。
【解决方案5】:

替代解决方案:

您实际上可以在浮动元素上放置margin-bottom 来推送 DOWN 下具有clear: both 的元素。

http://jsfiddle.net/9EY4R/

注意:提出此建议后,我必须立即撤回它,因为这通常不是一个好主意,但在某些有限的情况下可能合适;


<div class='order'>

    <div class='address'>
        <strong>Your order will be shipped to:</strong><br>
        Simon</br>
        123 Main St<br>
        Anytown, CA, US
    </div>

    <div class='order-details'>
        Item 1<br>
        Item 2<br>
        Item 3<br>
        Item 4<br>
        Item 5<br>
        Item 6<br>
        Item 7<br>
        Item 8<br>
        Item 9<br>
        Item 10<br>
    </div>

    <div class='options'>
        <button>Edit</button>
        <button>Save</button>
    </div>
</div>

带有项目的面板被称为order-details,这个css

.order-details
{
    padding: .5em;
    background: lightsteelblue;

    float: left;
    margin-left: 1em;

    /* this margin does take effect */
    margin-bottom: 1em;
}

在上面的小提琴中 - 黄色面板有一个margin-top,但除非它大于最高的浮动项目,否则它不会做任何事情(当然这就是这个问题的重点)。

如果您将黄色面板的margin-top 设置为 20em,那么它将是可见的,因为边距是从外部蓝色框的顶部计算的。

【讨论】:

    【解决方案6】:

    改为在主数据 div 中使用 'padding-top'。或者,或者,使用“padding-top”将主要数据 div 包装在一个中。

    【讨论】:

      【解决方案7】:

      尝试在其中一个浮动元素上设置下边距。或者,您可以将浮点数包装在父元素中,并使用 css hack 到 clear it without additional markup

      【讨论】:

        【解决方案8】:

        有时结合使用 position relative 和 margin 可以解决这些类型的问题。

        我将这种技术用于 WordPress 中的 alignright 和 alignleft 类。

        例如,如果我想要一个可以通过清除元素得到尊重的“下边距”。

        .alignright{
           float: right;
           margin-left: 20px;
           margin-top: 20px;
           position: relative;
           top: -20px;
        }
        

        对于您的示例,您可以执行类似

        的操作
        <div style="float: left;">Left</div>
        <div style="float: right;">Right</div>
        <div style="clear: both; margin-bottom: 200px; position: relative; top: 200px;">Main Data</div>
        

        【讨论】:

          猜你喜欢
          • 2014-07-27
          • 2012-07-26
          • 2023-02-24
          • 1970-01-01
          • 2011-09-19
          • 2022-10-07
          • 2010-10-25
          • 1970-01-01
          相关资源
          最近更新 更多