为什么添加或删除边框会改变边距的工作方式?

时间:2014-10-02 05:00:09

标签: html css border margin

如果我的容器内部有一个带边距的元素,那么元素边距不会在该容器内将其向下推,而是将容器本身向下推。仅此一点,虽然令人讨厌,但可能就是w3c决定如何运作。但奇怪的是,如果我在容器中添加一个边框,那么元素现在将在容器中向下推,然后容器将与上面的元素齐平(我想要的)。到目前为止,我使用的大多数容器都有边框,以便我可以告诉所有内容是如何排列的,但现在我已经决定开始添加背景颜色并去掉边距以使一切看起来更好我运行到了大量容器之间的间隙问题没有应用容器背景颜色。

如果我不清楚我创建了一个jsfiddle来演示这个问题,正如你可以通过查看html / js点击按钮只能切换边框的存在而没有别的东西。然而,容器之间的所有边距都会根据边界是否存在而改变。

http://jsfiddle.net/Tysonzero/p5fgjmrn/

HTML:

<div class="first-div">
</div>
<div class="second-div">
    <div class="inner-div">Test</div>
</div>
<button onclick="toggle()">Toggle Border</button>

CSS:

*
{
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}
.first-div
{
    background-color: red;
    min-height: 50px;
}
.second-div
{
    background-color: blue;
    min-height: 50px;
}
.inner-div
{
    margin: 10px;
    text-align: center;
}

JS:

toggle = function() {
    if (document.getElementsByClassName('second-div')[0].style.border) {
        document.getElementsByClassName('second-div')[0].style.border = "";
    }
    else {
        document.getElementsByClassName('second-div')[0].style.border = "1px solid";
    }
};

我希望它始终按照它的工作方式工作,因为IMO更有意义,而且对于我的项目,这是我需要的。我真的希望我不必做一些hacky,例如为所有东西添加1px透明边框并在必要时进行补偿。我尝试过使用overflow:auto;或溢出:隐藏。但两者都没有边界相同。溢出:自动;如果里面的元素大于父元素,或者如果你以某种方式使用负边距而不添加边框,则有时会创建滚动条,overflow:hidden;完全阻止滚动,而添加边框则不然。

是否有人知道我如何强制浏览器将所有内容视为具有边框(或至少使这样的问题不发生),并且任何人都可以解释这种行为吗?这似乎是无意的,但我可能是错的。

1 个答案:

答案 0 :(得分:2)

您问题的具体答案是collapsing margins,是W3C's BOX MODEL规范的一部分:


垂直边距可能会在某些框之间崩溃:

  • 正常流动中的两个或多个相邻的块箱垂直边缘坍塌。得到的边距宽度是相邻边距宽度的最大值。在负边距的情况下,负邻接边距的绝对值的最大值从正邻接边距的最大值​​中减去。如果没有正边距,则负相邻边距的绝对最大值将从零中扣除。注意。相邻的框可能由与兄弟姐妹或祖先无关的元素生成。
  • 浮动框和任何其他框之间的垂直边距不会折叠(甚至在浮动及其流入子项之间也不会崩溃)。
  • 建立新的块格式化上下文的元素的垂直边距(例如浮点数和溢出&#39;除了&#39;可见&#39;之外的元素)不会因其流入的子节点而崩溃。 / LI>
  • 绝对定位的盒子的边距不会崩溃(甚至没有流入的孩子)。
  • 内联块元素的边距不会崩溃(即使是流入的子元素也不会崩溃)。
  • 如果框的顶部和底部边距相邻,则边距可能会通过它折叠。在这种情况下,元素的位置取决于其与边缘正在折叠的其他元素的关系。
    • 如果元素的边距与其父元素的上边距折叠,则框的上边框边缘定义为与父元素相同。
    • 否则,元素的父母不参与边缘折叠,或仅涉及父母的底部边缘。元素顶部边框边缘的位置与元素底边非零时的位置相同。

已经应用了间隙的元素永远不会将其上边距与其父块的下边距折叠。

请注意,已折叠的元素的位置对其折叠边距的其他元素的位置没有影响;顶部边界边缘位置仅用于布置这些元素的后代。 根元素框的边距不会崩溃。


因此,当您添加边框时,您完全按照规范说的那样做,因此您没有边距。

有许多方法,修复和黑客可以解决这个问题,但对我来说,最直接和最容易的就是将overflow:auto;属性应用于要清除边距的div。

因此,在您的CSS中,您只需要像这样更改它:

.second-div
{
    background-color: blue;
    min-height: 50px;
    overflow:auto;
}

forked your fiddle具有更多边框,因此您可以注意到效果,看看效果如何