需要:CSS 网格系统和折叠边距
Posted
技术标签:
【中文标题】需要:CSS 网格系统和折叠边距【英文标题】:Wanted: CSS grid system AND collapsing margins 【发布时间】:2013-09-28 14:17:35 【问题描述】:我认为这是一个艰难的过程。
我使用使用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/
您可以看到,h1
的 margin-top 和 .header
的 margin-bottom 不会折叠。这是通过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><h1>Headerh1</h1></h1></div>
<div class="row">
<div class="column"><h2><h2>Col 1, float: left</h2></h2></div>
<div class="column"><h2><h2>Col 2, float: left</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 的边距崩溃。是否有机会通过margin-collapse 将元素彼此相邻放置,而无需手动将margin 设置为零?
否则。是否有机会在不创建新的块格式化上下文的情况下将设置元素彼此相邻?
编辑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 ─┐ │ │ ┄┄┄┴┄┄┄
│ │ └──────┘ │ │ └──────┘ │ │
│ └──────────┘ └──────────┘ │
└───────────────────────────┘
-------------------------------------------------------------
【问题讨论】:
没有 CSS 也没有小提琴? :// 呃,我明白了……我不这么认为:| +1,这是一个艰难的 如果我明白你想要什么(我不确定我是否明白),容器也只需要有一个浮动。 刚刚意识到这个问题是从 2013 年开始的 - :( 3年解决这个问题? :))) 【参考方案1】:这是不可能的:O
根据规范 (https://www.w3.org/TR/CSS2/box.html#collapsing-margins)
折叠条件:
两者都属于流入块级框 参与同一个区块 格式化上下文 没有行框,没有间隙,没有填充,没有边框 将它们分开(请注意,某些零高度线 框(见 9.4.2) 为此目的而被忽略。) 都属于垂直相邻的盒子边缘,即形成一个 以下对中的: 框的上边距及其第一个流入子元素的上边距 框的下边距和下一个流入的上边距 跟随兄弟姐妹 最后一个流入子节点的下边距和它的下边距 如果父级具有“自动”计算高度,则为父级 没有建立新的框的顶部和底部边距 块格式化上下文,并且计算的“最小高度”、零或“自动”为零 计算出的“高度”,以及 不 流入儿童块容器(例如 inline-blocks、table-cells 和 表格标题)不是块框
在这些情况下折叠边距将违反规则:
浮动之间的边距 盒子和任何其他盒子都不会塌陷(甚至在浮动和 其流入的孩子)。 建立新块格式的元素的边距 上下文(例如浮动和具有“溢出”而不是“可见”的元素) 不要与他们的流入孩子一起崩溃。 绝对定位的边距 盒子不会塌陷(即使是流入的孩子也不塌陷)。 行内块框的边距不会折叠(甚至 和他们流入的孩子)。 流入块级元素的下边距始终 与其下一个流入块级别的上边距一起折叠 兄弟姐妹,除非该兄弟姐妹有权限。 流入块元素的上边距折叠为 如果元素有,它的第一个流入块级子级的上边距 没有顶部边框,没有顶部填充,孩子没有间隙。 'height' 为 'auto' 且 'min-height' 为零的流入块框的下边距折叠 如果该框,则具有其最后一个流入块级子级的下边距 没有底部填充,没有底部边框和孩子的底部 边距不会与具有间隙的顶部边距一起折叠。 如果 '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-block
、position: absolute
、float
、flex
、grid
。
如果你不能将边距设置为零,也许你可以使用许多其他方法来打破边距功能
例如:让h1
为inline
并让div 有金色背景以打破margin-top: 50px;
:
根据保证金规范 (https://www.w3.org/TR/CSS2/box.html#margin-properties):
Margin 属性指定框的边缘区域的宽度。这 'margin' 速记属性设置所有四个边的边距,而 其他边距属性仅设置它们各自的一侧。 这些 属性适用于所有元素,但垂直边距不会 对非替换内联元素的任何影响。
【讨论】:
【参考方案2】:您实际折叠边距的唯一选项是以下选项:
不要在h1
上设置margin-top: 50px
,而是在.row
上设置margin-top: 50px
见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;
【讨论】:
【参考方案3】:我认为你做不到。可能最好的方法是根据一些条件定位边距并将其删除。
如果仅当带有h1
元素的.column
紧跟.header
时才会发生此问题,您可以构建更多特定的CSS 规则。这将覆盖边距并否定它。
.header + .row h1
margin-top: 0;
虽然这个答案中有很多如果,如果没有更多信息,很难解决。
【讨论】:
【参考方案4】:将.row
元素设为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>
【讨论】:
在这种情况下,我别无选择。如果你使用 Bootstrap 或 Foundation,你一定会浮动 你作弊了。将h1
的margin
设置为零不是解决方案
你说得对,伙计,我没有作弊。代码在那里,可见......无论如何,我编辑了答案。你为什么不试试上面的解决方案。如果您仍然坚持用其他可能的方法折叠边距并找到答案,请在此处分享。
对不起这个强词。但是你又做了。将firstcol
的边距设置为零不会折叠边距。【参考方案5】:
根据Mozzilla Developer Network:
浮动和绝对定位元素的边距永远不会塌陷。
如果保证第一个元素需要在任意数量的元素中折叠,则最好的选择是以下 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>
【讨论】:
【参考方案6】: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>
【讨论】:
这看起来很有希望,但是 1.table-row
不能是 100% 宽度。 2.这不是margin-collapse:table-row
just 禁用页眉的margin。【参考方案7】:
.header + *:last-child
h1
margin-bottom:0px;
.row + * :first-child
h2
margin-top:0px;
【讨论】:
【参考方案8】:关于边距折叠的文档非常清楚......
浮动和绝对定位元素的边距永远不会塌陷。
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
即使使用 flexbox 也无济于事,行为保持不变...
如果您知道哪些元素具有顶部边缘,也许您可以从first-of-type
选择器中得到一些东西...参见 sn-ps :
.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>
【讨论】:
【参考方案9】:在您的 CSS 中添加 *margin:0;
样式。它将避免所有浏览器中的所有默认边距。
【讨论】:
【参考方案10】:查看h1的默认显示属性如下,
h1
margin-top: 0.67em;/* which is around 11px*/
margin-bottom: 0.67em;/* which is around 11px*/
margin-left: 0;
margin-right: 0;
因此,您可以为行设置margin-top
,而不是为 h1 或 h2 设置边距顶部或底部,这与 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%;
【讨论】:
【参考方案11】:你已经听过好几次了...这似乎是不可能的...
我怀疑您不想使用选择器以免影响所有 h1 并解决可能不是 h1 且可能不相邻的其他元素(可能是 h2
,甚至是 p
) .header
元素的兄弟姐妹(可能只是 h1
没有 .header
包装,或者 p
底部边距 70px
)...
假设我是对的...您可以使用此选择器来解决所有此类情况...
.row .column > *:first-child
margin-top: 0;
这会将每行每列中第一个元素的top-margin
设置为0
。
认为这是最接近你想要的行为的方式......
让我知道这是否有帮助。
【讨论】:
以上是关于需要:CSS 网格系统和折叠边距的主要内容,如果未能解决你的问题,请参考以下文章
html 了解CSS网格系统//本文的基本网格系统//了解SitePoint上的CSS网格系统:http://www.sitepoin