【问题标题】:Why is adding or removing a border changing the way margins work?为什么添加或删除边框会改变边距的工作方式?
【发布时间】:2014-11-27 01:56:33
【问题描述】:

如果我有一个容器,其中的元素内部有一个边距,那么该元素的边距不会将其向下推到该容器内,而是向下推容器本身。仅此一项,虽然很烦人,但可能正是 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 那样以边框的方式工作,这更有意义,而对于我的项目来说,这正是我所需要的。我真的希望我不必做一些骇人听闻的事情,例如为所有内容添加 1px 透明边框并在必要时对其进行补偿。我试过使用溢出:自动;或溢出:隐藏。但两者都不等于有边界。溢出:自动;如果内部元素大于父元素,或者如果您以某种方式使用负边距而添加边框则不会,有时会创建滚动条,溢出:隐藏;完全防止滚动,而添加边框则不会。

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

【问题讨论】:

  • 我猜这是关于折叠边距,当没有边框时!
  • 我不确定您为什么使用内部 div 添加边距。如果这对您有用,我会将边距添加到 .second-div 。见jsfiddle.net/AuroraArcade/p5fgjmrn/2
  • 我希望两个容器齐平。我只想将元素与容器顶部分开。至于不同的元素,但使用相同的容器,我想要不同的边距,我不能只在第二个容器上放置填充。

标签: html css border margin


【解决方案1】:

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


某些框之间的垂直边距可能会折叠:

  • 正常流崩溃中块框的两个或多个相邻垂直边距。生成的边距宽度是相邻边距宽度的最大值。在负边距的情况下,从正相邻边距的最大值​​中减去负相邻边距的绝对值的最大值。如果没有正边距,则从零中减去负相邻边距的绝对最大值。笔记。相邻框可能由与兄弟或祖先不相关的元素生成。
  • 浮动框和任何其他框之间的垂直边距不会折叠(甚至在浮动框与其流入的子级之间也不折叠)。
  • 建立新块格式上下文的元素的垂直边距(例如浮动和具有“溢出”而不是“可见”的元素)不会与其流入的子元素一起折叠。
  • 绝对定位框的边距不会塌陷(即使是流入的子代也不会塌陷)。
  • 内联块元素的边距不会折叠(即使是它们的流入子元素也不折叠)。
  • 如果框的顶部和底部边距相邻,则边距可能会通过它折叠。在这种情况下,元素的位置取决于它与边距被折叠的其他元素的关系。
    • 如果元素的边距与其父元素的上边距折叠在一起,则框的上边框边缘被定义为与父元素的相同。
    • 否则,要么元素的父级不参与边距折叠,要么只涉及父级的底部边距。元素上边框边缘的位置与元素具有非零下边框时的位置相同。

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

请注意,被折叠的元素的位置不会影响被折叠的其他元素的位置;仅在布置这些元素的后代时才需要顶部边框边缘位置。 根元素框的边距不会折叠。


因此,当您添加边框时,您所做的正是规范所说的,因此您没有边距。

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

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

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

forked your fiddle 有更多的边框,所以你可以注意到效果,看看效果如何

【讨论】:

  • 溢出的主要问题:auto;是它在许多情况下创建了不需要的滚动条。例如,当我使用负边距或指定应该与包含元素相同但在不同浏览器上略有不同的固定高度时。是否有边框:0px 实心;什么样的东西会起作用?
  • 没有关注你。您可以在该 div 中添加 100 万个单词,它不会有任何滚动条,您自己试试看。要拥有滚动条,您需要定义大小,这将是另一种情况。另外,我正在回答您的具体问题(为什么)并提供解决方案(如何),您提到了边界的事情,但现在您再次要求边界,所以您让我感到困惑。话虽这么说,边框 0 是不可能的,因为它与边框相同:无,所以如果您想使用边框(并且无法想象原因),您可以做的最好的事情是使用 calc 属性并取消 1px大小
  • 如果我使用负边距,我经常会得到滚动条。我曾经做过*{overflow:auto;},但滚动条出现在我使用负边距的地方。您的解释和解决方案很棒,谢谢!我只是想知道是否有一种解决方案在使用负边距时不会导致滚动条。 border: 0 solid 如果它解决了这将是很棒的,因为它不会影响大小,但看起来我只需要解决滚动条等问题。
  • 这不是更清楚:“表达折叠边距意味着两个或多个框的相邻边距组合形成一个边距” - 从 w3.org 删除括号。
  • @ValterEkholm 这个答案有 7 年了,我的回答是 7 年前的样子,从源头复制和粘贴
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-04
  • 1970-01-01
  • 2021-06-17
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
相关资源
最近更新 更多