29

我认为这是一个艰难的过程。

我使用网格系统,利用float:left. 我可以用 重写它display:inline-block,但这不会改变任何事情。

假设我们有两列:

<div class="row"> 
    <div class="column">
        <!-- some content here -->
    </div>
    <div class="column">
        <!-- some content here -->
    </div>
</div>

如果我在其中放置一个带有 margin-top 的块元素(例如<h1>),我会在之前的内容中获得非折叠边距。这是正常的,因为浮动元素(或显示:内联块)总是如此。

但我希望利润率下降。我尝试了很多让它工作,但似乎每个将两个元素相邻放置的 CSS 都会破坏上面内容的折叠边距。

我知道,我可以使用 CSS 来获取元素的第一个子元素以摆脱边缘顶部。但在这种情况下它不适用,因为内容是使用 CMS 构建的,并且在我到达元素之前可能存在任意级别的元素深度。

没有 JavaScript 有没有办法做到这一点?

小提琴:http: //jsfiddle.net/HerrSerker/ZSV3D/

您可以看到,margin-top ofh1和 margin-bottom of.header不会塌陷。这是通过float:left..column

.header {
  font-size: 24px;
  background: rgba(0,255,0,0.1);
}
h1 {
  background: silver;
  margin-bottom: 50px;
  font-size: 28px;
}
.column {
  float: left;
  width: 50%;
  background: rgba(255,0,0,0.1);
}
h2 {
  background: gold;
  margin-top: 50px;
  font-size: 24px;
}
<div class="header"><h1>&lt;h1>Headerh1&lt;/h1></h1></div>
<div class="row">
    <div class="column"><h2>&lt;h2>Col 1, float: left&lt;/h2></h2></div>
    <div class="column"><h2>&lt;h2>Col 2, float: left&lt;/h2></h2></div>
</div>
<p>I want a 50 pixel margin between Header and the Cols, but the two margins don't collapse and I end up with 50 + = 100 pixel gap. If it would work, you wouldn't see the light red above col1 and col2</p>


编辑

我当然可以在 CSS 中使用一些后继运算符,例如header + .row .column h1 { margin-top: 0;}. 但这不是我想要的。我想要的是一种彼此相邻的设置元素的方式,它与包含的元素的边距折叠一起使用。


编辑2

因此,情况和问题再次简而言之。
问题比较简单。我有一些 CSS 代码,它允许我设置两个或多个相邻的 div,例如 float:left; 宽度:50%。在这些 div 内部是像 h2 这样具有上边距的元素。如果在 div 之前有一个带底边距的 h1。这种情况不允许 h1 和 h2 的边距崩溃。是否有机会通过边距折叠将元素彼此相邻放置,而无需手动将边距设置为零?

否则。在不创建新的块格式化上下文的情况下,是否有可能将设置元素彼此相邻?


编辑3:

-------------------------------------------------------------      
What it is:

 ┌─ .header ─────────────────┐
 │ ┌─ h1 ──────────────────┐ │
 │ │                       │ │
 │ └───────────────────────┘ │  ┄┄┄┬┄┄┄
 └───────────────────────────┘     ┆
                                   ┆ margin-bottom of h1
                                   ┆ 
 ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┼┄┄┄
                                   ┆
                                   ┆ margin-top  of h2
 ┌─ .row ────────────────────┐     ┆ not collapsing
 │ ┌─ .col ───┐ ┌─ .col ───┐ │  ┄┄┄┴┄┄┄
 │ │ ┌─ h2 ─┐ │ │ ┌─ h2 ─┐ │ │
 │ │ └──────┘ │ │ └──────┘ │ │
 │ └──────────┘ └──────────┘ │
 └───────────────────────────┘
      
-------------------------------------------------------------      
What I want:

 ┌─ .header ─────────────────┐
 │ ┌─ h1 ──────────────────┐ │
 │ │                       │ │
 │ └───────────────────────┘ │  ┄┄┄┬┄┄┄
 └───────────────────────────┘     ┆ margin-bottom of h1
                                   ┆ and margin-top  of h2
 ┌─ .row ────────────────────┐     ┆ collapsing
 │ ┌─ .col ───┐ ┌─ .col ───┐ │     ┆
 │ │ ┌─ h2 ─┐ │ │ ┌─ h2 ─┐ │ │  ┄┄┄┴┄┄┄
 │ │ └──────┘ │ │ └──────┘ │ │
 │ └──────────┘ └──────────┘ │
 └───────────────────────────┘
      
-------------------------------------------------------------      
4

11 回答 11

14

这是不可能的:O

根据规范(https://www.w3.org/TR/CSS2/box.html#collapsing-margins

崩塌条件:

  • 两者都属于参与相同块格式化上下文 的流入块级框
  • 没有线框,没有间隙,没有填充和没有边框将它们分开(请注意,某些零高度的线框(见 9.4.2)为此目的被忽略。)
  • 两者都属于垂直相邻的框边,即形成以下对之一:
    • 一个盒子的上边距和它的第一个流入孩子的上边距
    • 框的下边距和其下一个流入跟随兄弟的上边距
    • 如果父级具有“自动”计算高度,则最后一个流入子级的下边距和其父级的下边距
    • 没有建立新的块格式化上下文并且具有零计算的“最小高度”、零或“自动”计算的“高度”且没有流入子级的框的顶部和底部边距

不是块框的块容器(例如 inline-blocks、table-cells 和 table-captions)

在这些情况下折叠边距将打破规则:

  • 浮动框和任何其他框之间的边距不会塌陷(甚至在浮动框与其流入的子代之间也不会塌陷)。
  • 建立新块格式化上下文的元素的边距(例如浮动和具有“溢出”而不是“可见”的元素)不会与它们的流入子代一起折叠。
  • 绝对定位框的边距不会塌陷(即使它们的流入子代也不会塌陷)。
  • 内联块框的边距不会塌陷(即使是它们的流入子框也不塌陷)。
  • 流入块级元素的下边距总是与其下一个流入块级兄弟的上边距折叠,除非该兄弟有间隙。
  • 如果元素没有上边框、没有上边距且子元素没有间隙,则流入块元素的上边距与其第一个流入块级子元素的上边距一起折叠。
  • 'height' 为 'auto' 且 'min-height' 为零的 in-flow 块框的下边距与它最后一个 in-flow 块级子元素的底部边距折叠,如果该盒子没有底部填充并且没有底部边框和孩子的底部边距不会与具有间隙的顶部边距一起折叠。
  • 如果 'min-height' 属性为零,并且它既没有顶部或底部边框,也没有顶部或底部填充,并且它的 'height' 为 0 或 'auto',并且它不包含一个线框,其所有流入子级的边距(如果有)折叠。

弹性框也...(https://www.w3.org/TR/css-flexbox-1/#item-margins

相邻弹性项目的边距不会折叠。

网格也...(https://www.w3.org/TR/css-grid-1/#item-margins

相邻网格项的边距不会折叠。

margin-top: 50px;使用以下解决方案之一是不可能崩溃的: inline-block, position: absolute, float, flex, grid


如果您不能将边距设置为零,也许您可​​以使用许多其他方法来打破边距功能

例如: let h1beinline并让 div 有金色背景来打破margin-top: 50px;

根据保证金规范(https://www.w3.org/TR/CSS2/box.html#margin-properties):

边距属性指定框的边距区域的宽度。'margin' 速记属性设置所有四个边的边距,而其他边距属性只设置它们各自的边。这些属性适用于所有元素,但垂直边距不会对未替换的内联元素产生任何影响

于 2016-06-15T14:13:16.427 回答
5

实际折叠边距的唯一选项,没有一些选择器技巧或 JavaScript,如下所示:

不要设置margin-top: 50px你的h1,但.row

看到这个小提琴

HTML

<div class="header">Header is normal div</div>
<div class="row">
    <div class="column"><h1>Col 1 is float: left</h1></div>
    <div class="column"><h1>Col 2 is float: left</h1></div>
</div>
<p>I want a 50 pixel margin between Header and the Cols, but the two margins don't collapse and I end up with 50 + = 100 pixel gap.</p>

CSS

.header {
  background: silver;
  height: 50px;
  margin-bottom: 50px;
  font-size: 24px;
}
.row {
  margin-top: 50px;
}
.column {
  float: left;
  width: 50%;
}
h1 {
  background: gold;
  font-size: 24px;
}
于 2016-06-16T07:32:34.923 回答
3

我不认为你能做到这一点。可能最好的方法是根据一些条件定位边距并将其删除。

如果此问题仅在.columnwithh1元素紧随其后时发生.header,您可以构建更多特定的 CSS 规则。这将覆盖边距并否定它。

.header + .row h1 {
    margin-top: 0;
}

不过,这个答案中有很多如果,如果没有更多信息,很难解决。

于 2016-06-15T10:25:00.933 回答
3

使.row元素 a flex,问题解决...

你为什么要漂浮它?

.header {
  background: silver;
  height: 50px;
  margin-bottom: 50px;
  font-size: 24px;
}

.row {
	display: flex;
}

.column {
  width: 50%;
}
h1 {
  background: gold;
  font-size: 24px;
}

.firstcol {
   margin-top: 0;
}
<div class="header">Header is normal div</div>
<div class="row">
    <div class="column"><h1 class="firstcol">Col 1 is float: left</h1></div>
    <div class="column"><h1 class="firstcol">Col 2 is float: left</h1></div>
</div>
<p>I want a 50 pixel margin between Header and the Cols, but the two margins don't collapse and I end up with 50 + = 100 pixel gap.</p>

于 2016-06-15T10:50:00.240 回答
2

display: table//会是一种选择吗table-rowtable-cell

.header {
  background: silver;
  height: 50px;
  margin-bottom: 50px;
  font-size: 24px;
  display: table-row;
}
.row {
  display: table-row;
}
.column {
  display: table-cell;
  width: 50%;
}
h1 {
  background: gold;
  margin-top: 50px;
  font-size: 24px;
}
<div class="header">Header is normal div</div>
<div class="row">
    <div class="column"><h1>Col 1 is float: left</h1></div>
    <div class="column"><h1>Col 2 is float: left</h1></div>
</div>
<p>I want a 50 pixel margin between Header and the Cols, but the two margins don't collapse and I end up with 50 + = 100 pixel gap.</p>

于 2016-06-15T22:50:48.843 回答
2

根据Mozzilla 开发者网络

浮动绝对定位元素的边距永远不会塌陷。

如果保证第一个元素需要在任意数量的元素中折叠,那么最好的选择是以下 CSS:

.header + * :first-child {
  margin-top: 0;
}

如果我正确理解了这个问题,那么这与您单独使用 CSS 所获得的一样接近。

演示:

.header {
    background: silver;
    height: 50px;
    margin-bottom: 50px;
}
.column {
    float: left;
    width: 50%;
}
h1 {
    background: gold;
    margin-top: 50px;
}
.header + * :first-child {
  margin-top: 0;
}
<div class="header">Header</div>
<div class="row">
    <div class="column"><h1>Col 1</h1></div>
    <div class="column"><h1>Col 2</h1></div>
</div>

于 2016-06-15T11:55:43.197 回答
2
.header + *:last-child {
      h1{
         margin-bottom:0px;
       }
}
 .row + * :first-child{
       h2{
         margin-top:0px;
      }
}
于 2016-06-21T12:56:38.617 回答
1

请参阅 h1 的默认显示属性如下,

h1{
margin-top: 0.67em;/* which is around 11px*/
margin-bottom: 0.67em;/* which is around 11px*/
margin-left: 0;
margin-right: 0;
}

因此,您可以为行设置而不是为 h1 或 h2 设置边距顶部或底部margin-top,这会得到与 h1 和 h2 分配的边距值相同的结果。现在,当您按照以下代码中所述调整浏览器大小时。您可能会注意到,在调整大小时,空间会减少和增加。但在某一时刻,它会停止,因为我们已经分配了顶部保证金 + 我们也已经有了默认的 h1 和 h2 保证金。

.header {
font-size: 24px;
  background: rgba(0,255,0,0.1);
}
h1 {
  background: silver;
  margin-bottom: 50px;
  font-size: 28px;
}
.column {
  float: left;
  width: 50%;
  background: rgba(255,0,0,0.1);
}
h2 {
 background: gold;
  margin-top: 50px;
  font-size: 24px;
}
.row{
  margin-top:7.5%;
}

但是如果我们删除 h1 和 h2 默认值,那么 和 之间的空间.header.column是分配给的空间.row(以 % 为单位),并且随着我们调整浏览器宽度的大小而减小。现在可以通过针对特定移动设备使用媒体查询来为 .column 分配 100% 的宽度。这样 col 2 被放置在 col 1 下方,宽度为 100%

body{
margin:0;
}
.header {
  font-size: 24px;
  background: rgba(0,255,0,0.1);
}
h1 {
  background: silver;
  font-size: 28px;
  margin:0;
}
.column {
  float: left;
  width: 50%;
  background: rgba(255,0,0,0.1);
}
h2 {
  background: gold;
  font-size: 24px;
  margin:0;
  }
.row{
  margin-top:7.5%;
}
于 2016-06-20T11:03:48.523 回答
1

在你的 CSS 中赋予*{margin:0;}风格。它将避免所有浏览器中的所有默认边距。

于 2016-06-15T17:44:15.160 回答
1

关于保证金崩溃的文档非常清楚......

浮动和绝对定位元素的边距永远不会塌陷。

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing

即使使用 flexbox 也无济于事,行为保持不变......

如果您知道哪些元素具有顶部边距,也许您可​​以从first-of-type选择器中得到一些东西......请参阅片段:

.header {
  background: silver;
  height: 50px;
  margin-bottom: 50px;
  font-size: 24px;
}
.column {
  float: left;
  width: 50%;
}
h1 {
  background: gold;
  margin-top: 50px;
  font-size: 24px;
}
.column h1:first-of-type {
  margin-top: 0;
}
<div class="header">Header is normal div</div>
<div class="row">
    <div class="column"><h1>Col 1 is float: left</h1></div>
    <div class="column"><h1>Col 2 is float: left</h1></div>
</div>
<p>I want a 50 pixel margin between Header and the Cols, but the two margins don't collapse and I end up with 50 + = 100 pixel gap.</p>

于 2016-06-15T09:38:32.780 回答
1

正如您已经多次听到的那样……这似乎是不可能的……

我怀疑您不想使用选择器以免影响所有 h1 并解决可能不是 h1 并且可能不是元素的相邻兄弟姐妹的其他元素(例如可能h2,甚至 a ) (可能只是没有包装器,或带边距底部)...p.headerh1.headerp70px

假设我是对的...您可以使用此选择器来解决所有此类情况...

.row .column > *:first-child {
  margin-top: 0;
}

这会将top-margin每行的每一列中的第一个元素设置为0.

认为这是最接近您可以获得所需行为的方式......

让我知道这是否有帮助。

于 2016-06-22T07:52:03.593 回答