CSS:浮动元素时边距折叠问题的干净解决方案

发布于 2024-11-13 11:00:43 字数 833 浏览 0 评论 0原文

HTML+CSS 示例:

<html>
  <body style="padding: 0; margin: 0;">
    <div style="float: right;">first</div>
    <div style="margin-top: 2em;">second</div>
  </body>
</html>

所需行为first div 浮动到窗口的右上角。 实际行为:它浮动在所需位置下方 2em 处。 原因: 边距折叠

尽管确定了问题,但我能想出的解决方案感觉就像黑客:

  • body 样式更改为 margin: -1px 0 0 0;顶部边框:1px 实线;
  • first 之前插入
  • 插入上面的 < firstsecond 之间的 div>

是否有一种干净、惯用的方法来避免此问题?

Example HTML+CSS:

<html>
  <body style="padding: 0; margin: 0;">
    <div style="float: right;">first</div>
    <div style="margin-top: 2em;">second</div>
  </body>
</html>

Desired behavior: the first div floats to the top-right of the window. Actual behavior: it floats 2em below the desired position. Reason: margin collapsing.

Despite identifying the problem, the solutions I can come up with feel like hacks:

  • change body style to margin: -1px 0 0 0; border-top: 1px solid;.
  • insert <div style="height: 1px; margin-bottom: -1px;"></div> before first
  • insert the above <div> between the first and second

Is there a clean, idiomatic way of avoiding this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

一曲爱恨情仇 2024-11-20 11:00:43

overflow: hide; 添加到 body 应该可以解决您的问题。它定义了一个新的块格式化上下文,如本文所述:溢出的魔力:隐藏

jsFiddle Demobody 标签是由 jsFiddle 自动添加的,这就是为什么我没有' t 将其包含在 HTML 标记中)

更新(感谢 @clairesuzy):如果 body 具有 padding: 0,则此解决方案不起作用。在我找到更好的方法之前,我只能建议在两个 div 周围添加一个包装器(至少我现在应该得到 @Marcel 的 downwote :)),我仍然认为这比 OP 发布的解决方案更干净。我通常会在浮动内容周围添加一个包装器(在大多数情况下更容易处理旧浏览器),大多数情况下不需要故意添加,因为它在逻辑和语义上都是必需的。

所以现在,我可以想出这个:

<body style="padding: 0; margin: 0;">
   <div id="container" style="overflow: hidden;">
       <div style="float: right;">first</div>
       <div style="margin-top: 2em;">second</div>
   </div>
</body>

jsFiddle 演示

更新 2 :经过深思熟虑并阅读评论后,我确实认为容器上的 overflow:hidden (或 overflow:visible 以外的任何内容)是正确的解决方案。它对我不起作用的唯一例外是将其设置在 body 元素上,无论如何,这是一种非常罕见的情况。在这些罕见的情况下,您可以尝试使用 position:absolute;顶部:0; right: 0; 而不是浮动。

另一种可能的解决方法:我还发现设置 display: inline-block; width: 100%;body 上确实有效。

jsFiddle 演示

Adding overflow: hidden; to the body should solve your problem. It defines a new block formatting context as described in this article: The magic of overflow: hidden.

jsFiddle Demo (the body tag is automatically added by jsFiddle, that's why I haven't included it in the HTML markup)

UPDATE (thx to @clairesuzy): This solution does not work if body has padding: 0. Until I can find a better way, I can only suggest to add a wrapper around the two divs (at least I deserve now @Marcel's downwote :)), which I still think is cleaner than the solutions posted by the OP. I normally add a wrapper around floated stuff anyways (makes it easier to handle older browsers most of the time), most of the time it does not need to be added deliberately, because it is logically and semantically required.

So for now, I can come up with this:

<body style="padding: 0; margin: 0;">
   <div id="container" style="overflow: hidden;">
       <div style="float: right;">first</div>
       <div style="margin-top: 2em;">second</div>
   </div>
</body>

jsFiddle Demo

UPDATE 2: After thinking it through, and reading comments, I really think that overflow: hidden (or anything other than overflow: visible) on the container is the right solution. The only exception where it did not work for me is setting it on the body element, which is a very rare situation anyways. In these rare situations, you can try using position: absolute; top: 0; right: 0; instead of floating.

Another possible workaround: I have also found that setting display: inline-block; width: 100%; on body works indeed.

jsFiddle Demo

紫罗兰の梦幻 2024-11-20 11:00:43

在父 div 上添加此 #parent {padding 1px 0; } 这对我来说是一个大问题,我花了很长时间才找到解决方案。我在一篇帖子上看到了大约 2 年,这修复了崩溃。

On the parent div add this #parent {padding 1px 0; } this was a huge issue for me and it took me for ever to find a solution. I saw on a post like 2 years and this fixes the collapse.

浊酒尽余欢 2024-11-20 11:00:43

解决方案

overflow: auto;overflow:hidden;overflow:scroll; 添加到 html>body 标签。

如果您想知道为什么

body 标记上创建块格式上下文 (BFC)。

为什么如果我仅将 overflow: hide; 添加到 body 则不起作用?

原因如下:

W3C#block-formatting

浮动、绝对定位元素、非块框的块容器(例如内联块、表格单元格和表格标题)以及具有“溢出”而非“可见”的块框(<除非该值已传播到视口)为其内容建立新的块格式化上下文。

W3C#overflow

UA 必须将根元素上设置的“overflow”属性应用到视口。

当根元素是 HTML“HTML”元素或 XHTML“html”元素,并且该元素具有 HTML“BODY”元素或 XHTML“body”元素作为子元素时,用户代理必须改为应用 '如果根元素上的值为“可见”,则“overflow”属性从第一个此类子元素到视口。

用于视口的“visible”值必须解释为“auto”。

传播值的元素必须具有“可见”的“溢出”使用值

在本例中,第一个此类子元素传播值的元素 引用body 标记。

换句话说,如果您将 overflow:hidden;overflow: auto;overflow:scroll; 添加到 body > 当 htmloverflow 属性的值为 visible 时,body属性的值为 visible溢出属性(隐藏autoscroll)将传播到视口。因此,根据第一个 W3C 引用,body 不会建立新的块格式化上下文。

但是,如果您将 overflow:hidden;overflow: auto;overflow:scroll; 添加到 html, “body”的溢出值不会被传播,因此会建立新的块格式化上下文。

SOLUTION

add overflow: auto; or overflow: hidden; or overflow: scroll; to both html and body tag.

IF YOU WANT TO KNOW WHY

Creating block formatting context(BFC) on body tag.

Why it does not work if I add overflow: hidden; only to body?

Here is why:

W3C#block-formatting

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

W3C#overflow:

UAs must apply the 'overflow' property set on the root element to the viewport.

When the root element is an HTML "HTML" element or an XHTML "html" element, and that element has an HTML "BODY" element or an XHTML "body" element as a child, user agents must instead apply the 'overflow' property from the first such child element to the viewport, if the value on the root element is 'visible'.

The 'visible' value when used for the viewport must be interpreted as 'auto'.

The element from which the value is propagated must have a used value for 'overflow' of 'visible'.

the first such child element and The element from which the value is propagated refer to body tag in this case.

In other words, if you add overflow: hidden; or overflow: auto; or overflow: scroll; to body while the value of html's overflow property is visible, the value of body's overflow property(hidden or auto or scroll) will be propagated to the viewport. So according to the first W3C quote, body would not establish new block formatting context.

However, if you add overflow: hidden; or overflow: auto; or overflow: scroll; to html, the overflow value of 'body' would not be propagated and hence establish new block formatting context.

腹黑女流氓 2024-11-20 11:00:43

float: left; 添加到第二个 div。

小提琴

Add float: left; to the second div.

fiddle

爱情眠于流年 2024-11-20 11:00:43

W3C 规范描述了有关折叠边距的内容:

“在本规范中,折叠边距一词是指两个或多个框(可以彼此相邻或嵌套)的相邻边距(没有非空内容、填充或边框区域,或间隙将它们分开)组合起来形成一个边距。”

http://www.w3.org/TR/CSS21/box.html #collapsing-margins

处理折叠边距的最佳方法是仅向具有折叠边距的元素的顶部或底部填充添加一个像素。

如果边距折叠在顶部..那么:

#element-with-collapsed-margin {
   padding-top:1px;
}

border-top 也可以解决这个问题,

#element-with-collapsed-margin {
   border-top:1px solid transparent;
}

如果你的底部边距折叠,那么你将添加 padding-bottom:1px;border-top:1px 实心透明;

基本上,当您将它们放在另一个之上时,或者甚至当您将元素嵌套在彼此内部时,顶部或底部的任何边框或填充都会阻止边距折叠。边距折叠

很好的参考:

http://reference.sitepoint.com/css/collapsingmargins

..

The W3C specs describes this about collapsing margins:

"In this specification, the expression collapsing margins means that adjoining margins (no non-empty content, padding, or border areas, or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin."

http://www.w3.org/TR/CSS21/box.html#collapsing-margins

best way to deal with collapsing margins is to just add one pixel to the top or bottom padding of the element that has the collapsed margin.

if the margin was collapsing on top.. then:

#element-with-collapsed-margin {
   padding-top:1px;
}

or border-top would fix this as well

#element-with-collapsed-margin {
   border-top:1px solid transparent;
}

if your bottom margin is collapsed then you would add padding-bottom:1px; or border-top:1px solid transparent;

basically any border or padding on top or bottom will stop the margins from collapsing when you have they above one another or even when you have elements nested inside each other that have margin collapse

good reference:

http://reference.sitepoint.com/css/collapsingmargins

..

离不开的别离 2024-11-20 11:00:43

overflow:hidden 不合适时,您可以使用另一个技巧:

.clr:before, .clr:after {
    display: table;
    content: " ";
    clear: both;
    font-size: 0;
}

此代码段还具有包含所有浮动的副作用。

Another trick that you can use when overflow:hidden is not suitable:

.clr:before, .clr:after {
    display: table;
    content: " ";
    clear: both;
    font-size: 0;
}

This snippet has the side-effect of containing all floats as well.

被翻牌 2024-11-20 11:00:43

这可能很奇怪,但在新版本的 Chrome 和 Mozilla 中,您可以通过添加带边框的包装 div 来实现所需的行为(第一个 div 位于右上角)

<html>
  <body style="padding: 0; margin: 0;">
    <div style="border: 1px solid black">
        <div style="float: right;">first</div>
        <div style="margin-top: 2em;">second</div>
    </div>
  </body>
</html>

It might be strange but in new versions of Chrome and Mozilla you can achieve the desired behavior (first div is at the top right) by adding wrapper div with border

<html>
  <body style="padding: 0; margin: 0;">
    <div style="border: 1px solid black">
        <div style="float: right;">first</div>
        <div style="margin-top: 2em;">second</div>
    </div>
  </body>
</html>
醉酒的小男人 2024-11-20 11:00:43

clear: right 添加到第二个秒

<html>
  <body style="padding: 0; margin: 0;">
    <div style="float: right;">first</div>
    <div style="clear: right">second</div>
  </body>
</html>

add clear: right to second second

<html>
  <body style="padding: 0; margin: 0;">
    <div style="float: right;">first</div>
    <div style="clear: right">second</div>
  </body>
</html>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文