边距顶端不起作用:


74

<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检查了它。
Zain Shaikh,2010年

4
这里的大多数答案都提供了解决此问题的方法,这很好,但是如果您想要一个(长期而又困难的)答案,而该答案实际上可以解释为什么会首先发生,请参见mine
Mark Amery

大多数答案都说“如何”而不是“为什么”!
Ayub

Answers:


73

您可以将两个浮动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>

编辑—为这个已有5年历史的答案添加一点点:我认为造成混乱行为的原因是利润率下降的过程有些复杂。OP中原始HTML的一个好技巧是添加一个CSS规则,如下所示:

div { border: 1px solid transparent; }

of!现在(没有我的附加要求<div>)可以正常工作!好吧,除了边界上的多余像素。特别是,我认为这是clear: both工作方式与边距折叠规则的结合,这些规则会导致OP中的代码出现意外的布局。

再次编辑-有关完整(并且我认为完全准确)的故事,请参阅Mark Amery的出色答案。细节有一些复杂性,这个答案可以掩盖。


您能详细说明一下吗?
Salman Virk

@ user395881很好,浏览器执行的边距计算与相同布局上下文中的元素有关。对于浮动元素,相对于其他本地浮动元素以及(与行内内容)(我认为)也要计算出边距。但是这些静态块元素处于不同的上下文中。我同意,布局规则复杂且难以理解。W3C文档中有一些说明某些内容的图。
Pointy

有效地不存在“浮动”元素显然是不正确的,以作为保证金无效的解释。如果仅此而已,那么我们希望可以仅从父元素的顶部开始而不是浮动元素的底部看到已清除div的空白框的顶部。相反,我们看到的边缘不发生作用,在所有; OP原始代码中的已清除div最终定位成比浮动div实际不存在的位置。您的解决方案有效,但是对问题原因的解释可能不正确。
马克·阿默里

@MarkAmery我真的不确定我明白你在说什么。
尖尖的

@Pointy在给定OP代码的情况下,具有margin-top的div的位置与删除浮动div或给定position:absolute的位置不同。这意味着,为了保证金计算的目的,效果不能下降到不是真的“存在”的浮动div。
Mark Amery

21

虽然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包装器的情况下,这可能会很有用。


这是一个非常聪明的方法。您还可以将〜<div style =“ clear:both;”> </ div>〜的高度设置为
〜margin

17

规范中此背后的逻辑是弯腰的,并且涉及清除规则和利润率下降的规则之间的复杂相互作用。

你可能熟悉的常规CSS盒模型,其中内容框包含一个内填充盒包含一个内边界框包含一个内缘盒

箱型图

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

除“ none”以外的其他值可能会导致清除。间隙可防止边距折叠,并充当元素边距顶部上方的间距。

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

在边距框顶部上方添加了带有“间隙”的框模型

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

通过首先确定元素顶部边界的假定位置,可以计算出设置了“清除”的元素的间隙。如果元素的“ 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其设置为none第三分区,而不是both。那么上面的代码段是什么样的?

<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规范“由于浮动中没有浮动因此在浮动框之前和之后创建的未定位区块框会垂直流动,就好像该浮动不存在一样) ”,但是我们的第三个div上有很多负载,margin-top紧随两个浮动div之后;两个浮动div不应出现在主体顶部,而第三个div则应位于其下方200px下方吗?

不会发生这种情况的原因是,第三个div的边距塌陷到divs父级的边距中(在本例中为body,但是如果将所有三个div包装在父div中,则会发生相同的行为)。该折叠利润率规范(以下引用省略一些无关的细节)告诉我们:

相邻的垂直边距崩溃...

当且仅当以下情况时,两个边距相邻

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

在我们的示例中,第三个div当然不是人体的第一个子对象,而是它的第一个流入子对象。请注意,根据https://www.w3.org/TR/CSS22/visuren.html#positioning-scheme

如果某个元素是浮动的,绝对定位的或者是根元素,则该元素被称为流出。一个元素被称为在流如果不是乱流。

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

元素的顶部边框边缘不超过相关的浮动

从而:

引入了清除功能,边距按照8.3.1中的规则崩溃

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

然后将间隙量设置为以下较大者:

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

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

注意:在评估它们与现有Web内容的兼容性之前,都允许这两种行为。将来的CSS规范将需要一个或另一个。

注意:间隙可以为负或零。

在开始应用这些规则之前,我们立即遇到了麻烦。请记住,塌陷保证金,我们必须考虑到在假定情况下clearnone?好吧,在我们要计算要使用的游隙的这种非假设情况下,它并不存在,因为游隙的存在会抑制它。回想一下前面引用的8.3.1中崩溃边距规则,边距规则仅在以下情况下才邻接

  • 没有线框,没有间隙,没有填充和没有边框将它们分开

(添加了重点)。因此,第三个div的上边距和其父级的上边距不再相邻。我们可以按照上面引用的规则,通过保留clear: nonepadding-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施加间隙,以向上拖动其顶部边界以接触其上方浮动元素的底部外边缘(也称为边界边缘)。因此,如果浮动元素的高度分别为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>

(请注意,如果您使用浏览器的开发工具检查以上代码段中的第三个div,则仍然可以看到div上方的200px的上边距,超出了所有其他内容的范围-仅仅是较大的负间隙将整个边距框向上拉起。)

简单!


这个-好吧,我想说的是“有道理”,但这不是很正确-确实是正确的故事。我想得出的结论是,我没有做太多的工作,因为没有办法引入对布局没有影响(“厚度”为0px)的“边缘塌陷栅栏”。是对的吗?
尖尖的2016年

根据w3.org/TR/CSS22/box.html#collapsing-margins规范中的大,并根据流行的答案,对于容器/子折叠的情况,overflow: auto还是overflow: hidden在父容器上,@ Pointy可以解决问题例如stackoverflow.com/a/6204990/1709587(尽管由于某些原因,如果容器是元素,则无法使用)。我不太确定为什么这样做,因为它取决于“块格式化上下文”的定义(我尚未研究并且目前尚不了解)。body
Mark Amery

@Pointy使用例如0.02px的围栏似乎也可以工作(至少在Chrome中-可能是特定于浏览器的),尽管对布局没有明显影响。但是,较小的栅栏(如0.01px)不起作用。为什么?不知道。
Mark Amery

是的,当我处理自己的问题版本时,我半记得尝试使用越来越小的边框宽度(等),直到我厌倦了它并决定我并不太在意。这无疑是令人惊讶的行为。
Pointy 2016年

根据规范:“建立新块格式上下文的元素(例如浮点数和具有“可见”以外的“溢出”的元素)的边距不会随其流入子元素而崩溃。” 至于为什么这样做(就像从CSS2到CSS2.1的许多其他BFC相关更改一样),我不确定,但是我做了一个有根据的猜测。它似乎无法与body元素一起使用的原因是,当html发生溢出时,主体元素对html失去了其溢出属性:visible
BoltClock

8

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像素边距的预期效果。这是一个示例的链接

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


4

替代解决方案:

实际上,您可以margin-bottom在浮动元素上放一个,以将向下推到具有的元素下方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,则将可见,因为边距是从外部蓝色框的顶部计算的。


3

请在您的主数据div中使用“ padding-top”。或者,也可以将主数据div与“ padding-top”包装在一起。



0

有时,相对头寸和保证金的组合可以解决这类问题。

我将这种技术用于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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.