CSS margin 重叠(margin collapse)

margin 重叠(margin collapse)

首先有两个地方是我自己以前也没有注意的

  • 非替换元素的内联元素(<span>, <code>等), 设置上下 margin 没有用. 但是设置左右 margin 是有效果的. 而替换元素(<img> 等), 设置上下左右四个 margin 都有效果

    • 在这里插入图片描述
  • 其次就是只有上下 margin 会发生重叠(这个说法不严谨, 后面会解释).

进入正题, 上下 margin 重叠时, 谁的值(绝对值)更大最终的 margin 大小就是谁的值. 如果上下 margin 大小相同也是这样.

margin 重叠的三种情况

相邻的兄弟节点
<div class="box">
  <div style="margin-bottom: 1rem;">123</div>
  <div style="margin-top: 2rem;">abc</div>
</div>
.box {
  border: 1px solid;
}

最终合并的 margin 大小为 2rem
在这里插入图片描述

如果想阻止这种情况 margin 合并很简单, 就是破坏相邻这个条件, 因为两个都是块元素, 给他们中间增加 <br/> 换行就可以啦😀

<div class="box">
  <div style="margin-bottom: 1rem;">123</div>
  <br>
  <div style="margin-top: 2rem;">abc</div>
</div>

在这里插入图片描述

没有内容将父子分开

📕如果没有 border, padding, 行内元素, 格式化上下文(BFC(Block Formatting Context)) 或者清除浮动将一个父元素的上 margin 与其子元素的上 margin 分开; 重叠的部分溢出父元素.

<div style="margin-top: 1rem; background-color: salmon;">
  <div style="margin-top: 2rem;">123</div>
</div>

父子元素除了 margin 外都没有设置任何属性. 但是父元素离页面顶部的高度是 2rem, 因为出现了 margin 重叠.
在这里插入图片描述

📕父子元素出现 margin 重叠的第二种情况是没有 border, padding, 行内元素, height 或者 min-height 将一个父元素的下 margin 与其子元素的下 margin 分开, 那么 margin 就会重叠. 重叠的部分溢出父元素.
在这里插入图片描述

我知道此刻你的心里在想什么🤡你在想如果第一种情况和第二种情况同时发生会怎么样呢? 必须满足.

<div style="margin-bottom: 3rem;">456</div>
<div style="margin-top: 1rem; background-color: salmon;">
  <div style="margin-top: 2rem;">123123123123123123123123</div>
</div>

从下面的内容看, 前两个块元素满足兄弟节点 margin 重叠, 后两个块元素之间满足父子节点 margin 重叠, 且两种情况的重叠部分又重叠, 最终的重叠大小为 3rem, 大者获胜🥇
在这里插入图片描述

🔈关于这种情况, 在开发时需要注意, 如果我们设置子元素 margin 是为了和父元素保持一定距离就可能出现 margin 重叠, 所以这时候改用设置父元素 padding 来达到相同的效果.

空的块级元素

如果一个空元素没有设置 border, padding, 行内元素, height, min-height 来将上下 margin 分开, 那么上下 margin 也将重叠.

<div style="margin-top: 1rem; margin-bottom: 2rem;"></div>

来看上面的空元素, 即便同时设置了上下 margin, 但最终的 margin 高度还是 32px(2rem).
在这里插入图片描述

但是如果稍微加点内容(行内元素)就不一样了
在这里插入图片描述

其他复杂的规则

其实 CSS-TRICKS: The Rules of Margin Collapse 这篇文章里介绍了一些开发人员认为 margin 重叠的复杂难懂. 特别是不同情况重合在一起时, 但是还是有一些情况更加常见需要注意.

第一, 即便某个 margin 的值为 0, 上述规则仍然使用

负值 margin

如果参与重叠的 margin 中包含负值, 那么重叠之后的值为最大的正 margin 与最小(最负)的负 margin 的和.

<div style="margin-bottom: 5rem;">456</div>
<div style="margin-top: 1rem; background-color: salmon;">
  <div style="margin-top: -2rem;">123123123123123123123123</div>
</div>
可以看到, 最后的重叠 `margin` 为 `3rem(=5rem-2rem)`

在这里插入图片描述

那如果有两个负值 margin 又怎么样呢, 同样的重叠之后的 margin1rem(=5rem-4rem)
在这里插入图片描述

让我们考虑最最最最后一种情况, 三个 margin 全为负. 全是负的话依然是绝对值最大的负值为最后合并后的值.

<body style="padding-top: 5rem;">
  <div style="margin-bottom: -1rem;">456456456456456</div>
  <div style="margin-top: -2rem; background-color: salmon;">
    <div style="margin-top: -3rem;">123123123123123123123123</div>
  </div> 
</body>

在三个 margin 中, 绝对值最大的 margin-3rem, 那么合并后的 margin 值为 -3rem
在这里插入图片描述

floatabsolute 定位的元素 margin 永不重叠

<div style="margin-bottom: 1rem;">456</div>
<div style="float: left; margin-top: 1rem;">123</div>

第一个 div 不浮动, 第二个浮动, 两者不发生 margin 重叠
在这里插入图片描述

<div>我是凑热闹的~~~~</div>
<div style="position: relative; margin-top: 1rem; background-color: pink;">
  <div style="position: absolute; margin-top: 3rem; background-color: skyblue;">123</div>
</div>

相对定位的 div 和决定定位的 div 满足父子组件 margin 重叠的条件但是并没有重叠.
在这里插入图片描述

flex 子项元素没有 margin 重叠

<div style="display: flex; flex-direction: column;">
  <div style="flex: 0 0 auto; margin: 10px 10px;">111</div>
  <div style="flex: 0 0 auto; margin: 10px 10px;">222</div>
  <div style="flex: 0 0 auto; margin: 10px 10px;">333</div>
  <div style="flex: 0 0 auto; margin: 10px 10px;">444</div>
</div>

在这个 flex 布局中, 主轴的方向是从上到下, 相邻元素之间符合 margin 重叠的第一种情况, 但是并没有发生重叠.
在这里插入图片描述

不是上下, 而是块元素堆叠方向

一般大家都会说是上下 margin 才会重叠, 这个说法不错, 因为大多数情况文档流是从上到下, 块元素也是从上到下排列的. 但是如果我们修改书写顺序, 比如古代文字是从右到左书写的, 那么这时候视觉上发生 margin 重叠的不是上下, 而是左右.

📕所以严谨的说法是, 发生 margin 重叠的方向是块元素排列方向. 如果从上到下写字, 就是视觉上下 margin 重叠; 如果从左到右写字, 就是视觉左右 margin 重叠.

<div style="writing-mode: vertical-rl;">
  <div style="margin-block-start: 10px; margin-block-end: 10px;">123</div>
  <div style="margin-block-start: 10px; margin-block-end: 10px;">456</div>
</div>

在代码中我们使用 margin-block-startmargin-block-end 这两个 CSS 属性来表示块排列开始方向和结束方向的 margin
在这里插入图片描述

谢谢你看到这里, 本文仅作了有限的讨论和探索, 不足之处请指出

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值