【问题标题】:Margin on child element moves parent element子元素的边距移动父元素
【发布时间】:2010-12-18 06:22:37
【问题描述】:

我有一个 div (parent),其中包含另一个 div (child)。 Parent 是 body 中的第一个元素,没有特定的 CSS 样式。当我设置

.child
{
    margin-top: 10px;
}

最终结果是我孩子的顶部仍然与父母对齐。我的父母没有将孩子向下移动 10 像素,而是向下移动了 10 像素。

我的DOCTYPE 设置为XHTML Transitional

我错过了什么?

编辑 1
我的父母需要有严格定义的尺寸,因为它有一个必须从上到下显示的背景(像素完美)。所以在它上面设置垂直边距是不行

编辑 2
这种行为在 FF、IE 和 CR 上都是一样的。

【问题讨论】:

  • 这种行为没有任何意义。保证金应该留在父级内部。不移动父级。谁编写了这些规则。
  • +2 最后评论。严重的是,这个rule 困扰着我。 “每次都有 60% 的时间有效”——这就是利润。
  • 我完全同意最后两位评论者的观点。疯了吧。有趣的是,为父级添加 1px 边框使其正常工作,但这意味着您有一个边框......如果这是预期的行为,那么这很荒谬
  • 这让我想起了默认的 box-sizing 规则:“我们需要运送一个箱子。箱子不能大于 100 厘米。我们需要在箱子内留 10 厘米的填充物以确保我们的内容在运输过程中不会损坏。让我们把盒子做成 120 厘米!“开个玩笑。

标签: css xhtml margin nested


【解决方案1】:

玩父母的显示

.parent{
     display: inline-block;
     width: 100%;
}

.parent{ display: flex; }

【讨论】:

    【解决方案2】:

    Child elements with margins within DIVs 找到了替代方案您也可以添加:

    .parent { overflow: auto; }
    

    或:

    .parent { overflow: hidden; }
    

    这可以防止到collapse 的边距。边框和填充做同样的事情。 因此,您还可以使用以下方法来防止上边距崩溃:

    .parent {
        padding-top: 1px;
        margin-top: -1px;
    }
    

    2021 年更新:如果您愿意 drop IE11 support,也可以使用新的 CSS 构造 display: flow-root。有关块格式化上下文的全部详细信息,请参阅 MDN Web Docs


    应大众要求更新: 折叠边距的全部意义在于处理文本内容。例如:

    h1, h2, p, ul {
      margin-top: 1em;
      margin-bottom: 1em;
      outline: 1px dashed blue;
    }
    
    div { outline: 1px solid red; }
    <h1>Title!</h1>
    <div class="text">
      <h2>Title!</h2>
      <p>Paragraph</p>
    </div>
    <div class="text">
      <h2>Title!</h2>
      <p>Paragraph</p>
      <ul>
        <li>list item</li>
      </ul>
    </div>

    因为浏览器会折叠边距,所以文本会按照您的预期显示,并且 &lt;div&gt; 包装标签不会影响边距。每个元素确保它周围有间距,但间距不会加倍。 &lt;h2&gt;&lt;p&gt; 的边距不会相加,而是相互滑入(它们折叠)。 &lt;p&gt;&lt;ul&gt; 元素也是如此。

    遗憾的是,对于现代设计,当您明确想要一个容器时,这个想法可能会让您感到厌烦。这在 CSS 语言中称为新的block formatting contextoverflow 或保证金技巧会给你。

    【讨论】:

    • 我想知道为什么会发生这种情况,这对任何人都有什么好处。这个“功能”应该是什么情况。
    • @MuhammadUmer,这与文本内容有关。例如,一系列&lt;h2&gt;&lt;p&gt;&lt;ul&gt; 不会以这种方式得到奇怪的间隙或“双倍”边距。
    • 你能举个例子吗?假设我有 div 作为背景。其中包含 h1、h2 和 p。现在我想将 h1 向下移动一点,这样它就不会太靠近背景 div 的上方边缘,但不会扩展 h1 元素本身。我想增加上边距。这是显而易见的。但是当我这样做时,光荣的背景决定随之而来。这是一个功能。这如何有助于 h1、h2 和 p 之间的间距。帮我看看你在说什么。
    • 我为你添加了一个例子
    • 我希望它能增加更多的利润。在我的开发生涯中,利润率下降是迄今为止最烦人的事情。如果我用margin: 5px 10px; id 将 2 个 div 彼此相邻放置,则期望 2 个 div 距顶部 5 像素,它们之间 20 像素,而不是距顶部 5 像素和它们之间 10 像素。如果我想要它们之间的 10 像素,id 已经指定了margin: 5px 5px;。老实说,我希望有一个可以阻止所有边距崩溃的根本规则。我讨厌我必须将纸上的页边距加倍,才能让它们在屏幕上真正做我想做的事。还有这个最重要的东西......真是一场灾难
    【解决方案3】:

    为了防止“div parent”使用“div child”的边距:
    在父级中使用这些 css:

    • 浮动
    • 填充
    • 边框
    • 溢出

    【讨论】:

      【解决方案4】:

      整洁的纯 CSS 解决方案

      使用以下代码将无内容的第一个子元素添加到无意移动的 div:

      .parent:before
      {content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}
      

      这种方法的优点是您不需要更改任何现有元素的 CSS,因此对设计的影响很小。接下来,添加的元素是一个伪元素,它在 DOM 树中是 not

      对伪元素的支持非常广泛:Firefox 3+、Safari 3+、Chrome 3+、Opera 10+ 和 IE 8+。这适用于任何现代浏览器(请注意较新的 ::before,它在 IE8 中不受支持)。

      上下文

      如果元素的第一个子元素具有margin-top,则父元素将调整其位置以折叠多余的边距。为什么?就是这样。

      鉴于以下问题:

      <style type="text/css">
      div {position: relative;}
      .parent {background-color: #ccc;}
      .child {margin-top: 40px;}
      </style>
      
      <div class="parent"><!--This div moves 40px too-->
          <div class="child">Hello world!</div>
      </div>
      

      您可以通过添加包含内容的子项(例如简单空间)来解决此问题。但是我们都讨厌为纯设计问题添加空间。因此,请使用white-space 属性来伪造内容。

      <style type="text/css">
      div {position: relative;}
      .parent {background-color: #ccc;}
      .child {margin-top: 40px;}
      .fix {position: relative;white-space: pre;height: 0px;width: 0px;overflow: hidden;}
      </style>
      
      <div class="parent"><!--This div won't move anymore-->
          <div class="fix"></div>
          <div class="child">Hello world!</div>
      </div>
      

      position: relative; 确保正确定位修复。而white-space: pre; 让您不必添加任何内容(例如空格)来修复。 height: 0px;width: 0px;overflow: hidden; 确保您永远不会看到修复程序。

      您可能需要添加line-height: 0px;max-height: 0px; 以确保在古代IE 浏览器中高度实际上为零(我不确定)。如果它不起作用,您可以选择在旧的 IE 浏览器中添加&lt;!--dummy--&gt;

      简而言之,您只需使用 CSS 即可完成所有这些操作(无需向 HTML DOM 树添加实际的子节点):

      <style type="text/css">
      div {position: relative;}
      .parent {background-color: #ccc;}
      .child {margin-top: 40px;}
      
      .parent:before {content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}
      </style>
      
      <div class="parent"><!--This div won't move anymore-->
          <div class="child">Hello world!</div>
      </div>
      

      【讨论】:

      • 只有在绝望时才使用此解决方案,并且您不能为现有元素设置任何自定义 CSS - 否则使用真正的解决方案:为父级设置 overflow: hidden;
      【解决方案5】:

      我发现, 在您的 .css 中 >如果您将 div 元素的 display 属性 设置为 inline-block,它可以解决问题。并且保证金将按预期工作。

      【讨论】:

        【解决方案6】:

        虽然所有的答案都解决了这个问题,但它们伴随着权衡/调整/妥协,比如

        • floats,你浮动元素
        • border-top,这会将父元素向下推至少 1px,然后应该通过将 -1px 边距引入父元素本身来进行调整。当父级已经有 margin-top 的相对单位时,这可能会产生问题。
        • padding-top,效果和border-top一样
        • overflow: hidden,当父级应该显示溢出的内容时不能使用,比如下拉菜单
        • overflow: auto,为具有(故意)溢出内容(如阴影或工具提示的三角形)的父元素引入滚动条

        使用CSS3伪元素可以解决这个问题

        .parent::before {
          clear: both;
          content: "";
          display: table;
          margin-top: -1px;
          height: 0;
        }
        

        https://jsfiddle.net/hLgbyax5/1/

        【讨论】:

        • margin-top: -1px 似乎没有必要。但我喜欢这个。
        • 其实margin-top: -1pxheight: 0 似乎都没有必要。在 Chrome 中测试。但最好的解决方案。
        • 这个方法最有效,但不会考虑容器内最后一个元素的下边距。溢出不是一个平等的解决方法:隐藏;例如。
        • @MichaelGiovanniPumo 可以使用.parent:after...修改答案以使用最后一个元素的底部边距
        • 这绝对是当今最正确的答案。完美无瑕(前后都戴上),我希望人们敢于滚动过去!
        【解决方案7】:

        为子元素添加样式display:inline-block

        【讨论】:

          【解决方案8】:

          在我知道正确答案之前我发现的另一种解决方案是向父元素添加透明边框

          你的盒子会使用额外的像素...

          .parent {
              border:1px solid transparent;
          }
          

          【讨论】:

            【解决方案9】:

            如果合适的话,使用top 代替margin-top 是另一种可能的解决方案。

            【讨论】:

              【解决方案10】:

              这对我有用

              .parent {
              padding-top: 1px;
              margin-top: -1px;
              }
              
              .child {
              margin-top:260px;
              }
              

              http://jsfiddle.net/97fzwuxh/

              【讨论】:

                【解决方案11】:

                有趣的是,我最喜欢的这个问题的解决方案还没有在这里提到:使用浮点数。

                html:

                <div class="parent">
                    <div class="child"></div>
                </div>
                

                css:

                .parent{width:100px; height:100px;}
                .child{float:left; margin-top:20px; width:50px; height:50px;}
                

                在这里查看:http://codepen.io/anon/pen/Iphol

                请注意,如果您需要父级上的动态高度,它也必须浮动,因此只需将 height:100px; 替换为 float:left;

                【讨论】:

                  【解决方案12】:

                  父元素不能为空,至少在子元素之前放置&amp;nbsp;

                  【讨论】:

                  • 是的,有时只有这样才能有所帮助……或者最好这样写:
                     
                  【解决方案13】:

                  我也遇到过这个问题,但更喜欢防止负边距被黑,所以我放了一个

                  &lt;div class="supercontainer"&gt;&lt;/div&gt;

                  在它周围都有填充而不是边距。当然这意味着更多的精神分裂症,但这可能是正确完成这项工作的最干净的方法。

                  【讨论】:

                    【解决方案14】:

                    .child 中包含的元素的margin 正在崩溃。

                    <html>
                    <style type="text/css" media="screen">
                        #parent {background:#dadada;}
                        #child {background:red; margin-top:17px;}
                    </style>
                    <body>
                    <div id="parent">
                    
                        <p>&amp;</p>
                    
                        <div id="child">
                            <p>&amp;</p>    
                        </div>
                    
                    </div>
                    </body>
                    </html>
                    

                    在本例中,p 接收来自浏览器默认样式的margin。浏览器默认 font-size 通常为 16px。通过在 #child 上设置超过 16 像素的 margin-top,您会开始注意到它的位置移动。

                    【讨论】:

                      【解决方案15】:

                      这是正常行为(至少在浏览器实现中)。边距不会影响子代相对于其父代的位置,除非父代有内边距,在这种情况下,大多数浏览器会将子代的边距添加到父代的内边距中。

                      要获得你想要的行为,你需要:

                      .child {
                          margin-top: 0;
                      }
                      
                      .parent {
                          padding-top: 10px;
                      }
                      

                      【讨论】:

                      • 给父级加边框也会影响子级的外边距,试试.parent {border: solid 1px;}
                      • 边距不会添加到填充中...它单独应用。但视觉效果是一样的。
                      • 如果你想要一个上边距怎么办……?不是真正的解决方案。
                      • 就像feeela 说的——如果需要上边距,这并不是真正的解决方案。 vdboor 的答案更适合。
                      • 有很多解决方案,你只需要有足够的创造力。干杯。 :-)
                      猜你喜欢
                      • 2022-01-03
                      • 2017-11-03
                      • 1970-01-01
                      • 2011-07-19
                      • 2020-02-16
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-03-06
                      • 1970-01-01
                      相关资源
                      最近更新 更多