【问题标题】:Negative margin does not pull up floated siblings in Firefox负边距不会拉起 Firefox 中的浮动兄弟姐妹
【发布时间】:2016-11-30 10:40:19
【问题描述】:

我有一个包含一个标题和两个其他框的框。标题顶部有负边距,因此它呈现在框外。在除 Firefox 之外的所有浏览器中,标题都正确地拉出其兄弟框,但在 Firefox 中,框保持在原位。

如果我从盒子中移除浮动,但它们确实向上移动。除了给盒子负边距顶部之外,还有其他解决方法吗?

div {
  background: red;
  padding: 2rem;
  margin-top: 8rem;
  box-sizing: border-box;
}

div:after {
  display: table;
  content: "";
  clear: both;
}

div div {
  background: green;
  margin: 0 0 2rem;
  width: 45%;
  float: left; /* Remove this and float: right below and it works in FF */
}

div div + div {
  float: right;
}

h2 {
  margin-top: -8rem;
}
<div>
<h2>
Hello
</h2>
<div>
These boxes also render outside the red one.
</div>
<div>
In every browser except Firefox.
</div>
</div>

【问题讨论】:

    标签: html css firefox css-float margins


    【解决方案1】:

    您可以将浮动框包裹在非浮动容器中。 (注意:我为每个 div 赋予了自己的类,只是为了更清楚地知道哪些样式适用于哪个 div。)

    .d1 {background:red; padding:2rem; margin-top:8rem; box-sizing:border-box;}
    .d1:after {display:table; content:""; clear:both;}
    .d3 {float:left; background:green; padding:2rem; box-sizing:border-box; width:45%;}
    .d3 + .d3 {float:right;}
    h2 {margin-top:-8rem;}
    <div class="d1">
        <h2>Hello</h2>
        <div class="d2">
            <div class="d3">These boxes render outside the red one.</div>
            <div class="d3">In every browser.</div>
        </div>
    </div>

    【讨论】:

    • 我不喜欢在我的代码中添加一个额外的 div,但这显然是有效的,所以谢谢。
    【解决方案2】:

    首先我进一步简化为下面的minimal示例:

    * {
      box-sizing: border-box;
    }
    body {
      margin: 0;
    }
    .wrapper {
      background: red;
      padding: 2rem;
      margin-top: 8rem;
    }
    .wrapper > div {
      background: green;
      padding: 2rem;
      float:left;
    }
    .wrapper:after{
      content: '';
      clear:both;
      display: table;
    }
    h2 {
      margin-top: -8rem;
    }
    <div class="wrapper">
      <h2>Hello</h2>
      <div>These boxes also render outside the red one.</div>
    </div>

    为什么会这样?

    1. 首先尝试从wrapper 中删除padding,然后看到现在margin collapsing 将发挥作用,即使在Firefox 中也会显示相同的行为。 (wrapperpadding: 2rem 防止h2 的边距与wrapper 重叠)。很明显 margin colpasing 在这里没有任何作用。

          * {
            box-sizing: border-box;
          }
          body {
            margin: 0;
          }
          .wrapper {
            background: red;
            margin-top: 8rem;
          }
          .wrapper > div {
            background: green;
            padding: 2rem;
            float:left;
          }
          .wrapper:after{
            content: '';
            clear:both;
            display: table;
          }
          h2 {
            margin-top: -8rem;
          }
          <div class="wrapper">
            <h2>Hello</h2>
            <div>These boxes also render outside the red one.</div>
          </div>
    2. 现在尝试将float: left 切换为wrapper 中的div,您会看到浮动 容器存在负边距 的问题(在Firefox 中)。

          * {
            box-sizing: border-box;
          }
          body {
            margin: 0;
          }
          .wrapper {
            background: red;
            padding: 2rem;
            margin-top: 8rem;
          }
          .wrapper > div {
            background: green;
            padding: 2rem;
          }
          .wrapper:after{
            content: '';
            clear:both;
            display: table;
          }
          h2 {
            margin-top: -8rem;
          }
          <div class="wrapper">
            <h2>Hello</h2>
            <div>These boxes also render outside the red one.</div>
          </div>

    所以这是一个错误?

    文档只是这样说:

    允许边距属性为负值,但可能存在 特定于实现的限制。(来源:W3C

    看起来 Firefox 有一个老错误,我猜它仍然打开 - 请参阅 this Bugzilla link

    解决方案

    不要为具有负边距的容器保留 浮动 兄弟:

    * {
      box-sizing: border-box;
    }
    body {
      margin: 0;
    }
    .wrapper {
      background: red;
      padding: 2rem;
      margin-top: 8rem;
    }
    .wrapper > .float-wrap > div {
      background: green;
      padding: 2rem;
      float:left;
    }
    .wrapper > .float-wrap:after{
      content: '';
      clear:both;
      display: table;
    }
    h2 {
      margin-top: -8rem;
    }
    <div class="wrapper">
      <h2>Hello</h2>
      <div class="float-wrap">
        <div>These boxes also render outside the red one.</div>
      </div>
    </div>

    以下是包装浮动容器的代码的解决方案:

    div {
      background: red;
      padding: 2rem;
      margin-top: 8rem;
      box-sizing: border-box;
    }
    div:after {
      display: table;
      content: "";
      clear: both;
    }
    div > div > div {
      background: green;
      margin: 0 0 2rem;
      width: 45%;
      float: left;
    }
    div > div > div + div {
      float: right;
    }
    h2 {
      margin-top: -8rem;
    }
    div > h2 + div {
      padding: 0;
      margin: 0;
      background: none;
    }
    <div>
      <h2>Hello</h2>
      <div>
        <div>
          These boxes also render outside the red one.
        </div>
        <div>
          In every browser except Firefox.
        </div>
      </div>
    </div>

    【讨论】:

    • 谢谢。这基本上与安迪提供的解决方案相同,因为他比你早一个小时,我觉得我需要为此归功于他。不过,我会给你一个 +1 以获得真正彻底的答案。
    【解决方案3】:

    我认为这可能是除 Firefox 之外的所有浏览器中的错误。

    The Working Draft Collapsing Margin Spec states:

    • 浮动框的边距不会与任何其他边距一起折叠。
    • 如果一个盒子被折叠并应用了间隙到折叠的边距之一,那么这些边距不会折叠与父级的某些边距:如果间隙分别应用于顶部、右侧或左侧边距,则这些边距不会分别与父级的底部、左侧或右侧边距折叠。

    似乎除了 Firefox 之外的大多数浏览器都错误地允许浮动 div 边距折叠。但是,通过将clear 属性设置为div div css 将导致浮动保留在其容器中(参见下面的 sn-p)。这种行为更符合规范的规定。

    The Recommendation for positioning of floats 也让我相信您在其他浏览器中看到的可能不是预期的结果。规范建议似乎表明浮动项目应始终定位在其父容器中,除非另有明确说明。

    浮动框的外部顶部不得高于其包含块的顶部。


    演示向浮动添加清除将使它们包含在其父级中

    div {
      background: red;
      padding: 2rem;
      margin-top: 8rem;
      box-sizing: border-box;
    }
    
    div:after {
      display: table;
      content: "";
      clear: both;
    }
    
    div div {
      background: green;
      margin: 0 0 2rem;
      width: 45%;
      float: left;
      clear:right; // Adding this causes the floats to stay in their container
    }
    
    div div + div {
      float: right;
    }
    
    h2 {
      margin-top: -8rem;
    }
    <div>
    <h2>
    Hello
    </h2>
    <div>
    These boxes also render outside the red one.
    </div>
    <div>
    In every browser except Firefox.
    </div>
    </div>

    【讨论】:

    • 也许你是对的。我不得不说我更喜欢非 Firefox 的方式来处理这个问题。
    【解决方案4】:

    这取决于在浏览器中如何计算块结构。我通过将margin-top 替换为topposition 属性解决了这个问题

    div {
      background: red;
      padding: 2rem;
      margin-top: 8rem;
      box-sizing: border-box;
    }
    
    div:after {
      display: table;
      content: "";
      clear: both;
    }
    
    div div {
      position: relative;
      top: -12rem;
      background: green;
      width: 45%;
      float: left;
      /* Remove this and float: right below and it works in FF */
    }
    
    div div + div {
      float: right;
    }
    
    h2 {
      margin-top: -8rem;
      position: absolute;
    }
    

    工作小提琴:https://jsfiddle.net/nobalmohan/6sjhy1q3/

    我敢肯定,还有其他方法可以解决它。

    【讨论】:

    • “这取决于在浏览器中如何计算块结构”这是什么意思? :P 对我来说似乎是一个 Firefox 错误。我希望 not 像我在问题中所说的那样给每个嵌套的 div margin-top,但如果没有可用的错误修复,我可能会求助于该解决方案。
    • 另外,使用position: relative 而不是负边距的问题是容器框仍然与元素向上移动之前一样高。我不想那样。
    猜你喜欢
    • 2020-07-28
    • 2019-05-06
    • 2014-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    相关资源
    最近更新 更多