通缉:CSS网格系统和崩溃边距

时间:2013-09-23 15:42:12

标签: css margin grid-layout

我觉得这很难。

我使用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来获取元素的第一个子元素以摆脱margin-top。但在这种情况下它将不适用,因为内容是使用CMS构建的,并且在我到达元素之前可能存在任意级别的元素深度。

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

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

您可以看到,h1的边距顶部和.header的边距底部不会崩溃。这是float:left .column的{​​{1}}。

.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;}。但这不是我想要的。我想要的是一种设置元素彼此相邻的方式,它与包含元素的边缘折叠一起工作。


EDIT2

所以情况和问题再次简短 问题很简单。我有一些CSS代码,它允许我设置两个或多个div彼此相邻,如float:left;宽度:50%。这些div内部是像h2这样的元素,它们具有顶部边距。如果在div之前有一个带有底边距的h1。这种情况不允许h1和h2的边缘崩溃。是否有可能将元素放在边缘并且边缘折叠并且没有手动将边距设置为零?

或者其他。如果没有创建新的块格式化上下文,是否有可能将设置元素彼此相邻?


EDIT3:

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

.header    +---------------------+
.header    | +-----------------+ |
.header    | | h1              | |
.header    | +-----------------+ |  ----+---
.header    +---------------------+      |
                                        | margin-bottom of h1
                                        | 
           -----------------------------+---
                                        |
                                        | margin-top  of h2
.row       +---------------------+      | not collapsing
.row       | +-------+ +-------+ |  ----+---
.row       | | h2    | | h2    | |
.row       | | in    | | in    | |
.row       | | col 1 | | col 2 | |
.row       | +-------+ +-------+ |
.row       +---------------------+

-------------------------------------------------------------      
What I want:

.header    +---------------------+
.header    | +-----------------+ |
.header    | | h1              | |
.header    | +-----------------+ |  ----+---
.header    +---------------------+      | margin-bottom of h1
                                        | and margin-top  of h2
.row       +---------------------+      | collapsing
.row       | +-------+ +-------+ |  ----+---
.row       | | h2    | | h2    | |
.row       | | in    | | in    | |
.row       | | col 1 | | col 2 | |
.row       | +-------+ +-------+ |
.row       +---------------------+

-------------------------------------------------------------      

11 个答案:

答案 0 :(得分:10)

这是不可能的:O

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

折叠条件:

  
  • 都属于in-flow 块级别框   参加同一个街区   格式化上下文        
  • 没有行框,没有间隙,没有填充,没有边框   将它们分开(注意某些零高度线   盒子(见9.4.2)   为此目的被忽略。)        
  • 都属于垂直相邻的盒子边缘,即形成一个   以下对:      
        
    • 一个盒子的上边缘和第一个流入的孩子的上边缘      
    • 框的下边距和下一个流入的上边距       跟随兄弟      
    • 最后一个流入子的下边距及其下边距       如果父级具有“自动”计算高度,则为父级      
    • 未建立新的框的顶部和底部边距       阻止格式化上下文,并且零计算'min-height',零或'auto'       计算'高度',和   没有       流动儿童
     

阻止容器(例如内联块,表格单元格和   表格标题)不是块框

在这种情况下折叠边距将违反规则:

  
  • 浮动之间的边距   框和任何其他框不会崩溃(甚至没有浮动和   它的流动儿童)。        
  • 建立新块格式的元素的边距   上下文(例如浮点数和'溢出'除'可见'以外的元素)   不要与流动的孩子一起崩溃。        
  • 绝对定位的边距   盒子不会倒塌(甚至没有流入的孩子)。        
  • 内联块框的边距不会崩溃(甚至不会崩溃)   与他们的流动儿童)。        
  • 始终使用流内块级元素的下边距   在下一个流入块级别的上边缘折叠   兄弟姐妹,除非那个兄弟姐妹有空。        
  • 流入块元素的上边距会折叠   如果元素有,它是第一个流入块级子元素的上边距   没有顶部边框,没有顶部填充,并且孩子没有间隙。        
  • “高度”为“auto”且“min-height”为零的in-flow块盒的下边距折叠   如果是这个盒子,它的最后一个流入块级孩子的底部边缘   没有底部填充,没有底部边框和孩子的底部   保证金不会因具有清算的最高保证金而崩溃。        
  • 如果'min-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-blockposition: absolutefloatflexgrid

如果你不能将保证金设置为零,也许你可以使用许多其他方法来破坏保证金功能

例如:让h1成为inline并让div有金色背景来打破margin-top: 50px;

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

  

边距属性指定框的边距区域的宽度。该   'margin'速记属性为所有四方设定了保证金   其他保证金属性仅设定各自的一面。的这些   属性适用于所有元素,但垂直边距不会   对未替换的内联元素的任何影响

答案 1 :(得分:5)

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

不要在margin-top: 50px上设置h1,而是.row

请参阅this Fiddle

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;
}

答案 2 :(得分:3)

.row元素设为flex,问题解决了......

你为什么要漂浮它?

&#13;
&#13;
.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;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 3 :(得分:2)

我认为你不能那样做。可能最好的方法是根据一些条件定位保证金并将其删除。

如果此问题仅发生在.column h1元素紧跟.header之后,您可以构建更多特定的CSS规则。这将覆盖边际并否定它。

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

在这个答案中有很多if,但是如果没有更多信息则很难解决。

答案 4 :(得分:2)

根据Mozzilla Developer Network

  

浮动绝对定位元素的边距永不崩溃。

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

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

如果我正确理解了这个问题,那么就像单独使用CSS一样。

演示:

&#13;
&#13;
.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;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 5 :(得分:2)

display: table / table-row / table-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>

答案 6 :(得分:2)

.header + *:last-child {
      h1{
         margin-bottom:0px;
       }
}
 .row + * :first-child{
       h2{
         margin-top:0px;
      }
}

答案 7 :(得分:1)

关于保证金崩溃的文件很清楚......

  

浮动和绝对定位元素的边距永不崩溃。

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

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

如果你知道哪些元素有一个margin-top,也许你可以从<div class="parent"> <div class="child child--left"></div> <div class="spacer"></div> <div class="child child--right"></div> <div class="child child--right"></div> </div> 选择器中得到一些东西...参见片段:

&#13;
&#13;
first-of-type
&#13;
.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;
}
&#13;
&#13;
&#13;

答案 8 :(得分:1)

在你的CSS中给出*{margin:0;}样式。它将避免所有浏览器中的所有默认边距。

答案 9 :(得分: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的空间(以%为单位),并且随着我们调整大小而减少浏览器宽度。现在,通过定位特定的移动设备,可以使用媒体查询将宽度分配为100%.column。因此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%;
}

答案 10 :(得分:1)

你已经多次听过......这似乎不可能......

我怀疑你不想使用选择器,以免影响所有h1并解决可能不是的其他元素(如h2,甚至p) h1并且可能不是.header元素的兄弟姐妹(可能只有h1没有.header包装,或p有边距70px} ... < / p>

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

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

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

认为这是最接近你可以达到预期的行为......

Lemme知道这是否有帮助。