haizlin/fe-interview

[css] 第16天 请描述margin边界叠加是什么及解决方案

haizhilin2013 opened this issue · 16 comments

第16天 请描述margin边界叠加是什么及解决方案

xuech commented

可以使用BFC?

1,使用padding代替,但是父盒子要减去相应的高度
2,使用boder(透明)代替(不推荐,不符合书写规范,如果父盒子子盒子时有颜色的不好处理)
3,给父盒子设置overflow:hidden(如果有移除元素无法使用)
4,给父盒子设置1px的padding
5,给父盒子设置1px的透明border,高度减1px
6,子盒子使用定位position
7,子盒子浮动, 但是居中比较难以控制
8,给子盒子设置display: inline-block;
9,子盒子上面放一个table标签

若是相邻块元素垂直外边距的合并,合并之后会取两者中的最大值
若是嵌套块元素垂直外边距的合并,合并会形成一个外边距,合并到父元素的外边距并取其中的最大值(margin塌陷),解决方案:1.为父元素定义1px的上边框或上边距2.为父元素添加oveflow:hidden

在格式化文档流里 横向 纵向的margin会发生叠加 取最大值
解决方法:将其中一个元素放入一个新的格式化文档流中(BFC)

margin 的边界叠加发生在竖直方向上(左右方向上不会叠加)。兄弟 DOM 节点、父元素中的第一个子节点、以及最后一个尾节点都会产生 margin 边界叠加的现象。由于 CSS 早期主要用在文字、图片排版上,因此上下 margin 的叠加是符合预期效果的。

margin 边界叠加从结果上来看就是以最大的值为准。

<style>
  .b1 {
    width: 100px;
    height: 100px;
    margin-bottom: 30px;
  }
  // 最终两个 div 的 margin 为 40px,以最大的值为准。
  .b2 {
    width: 100px;
    height: 100px;
    margin-bottom: 40px;
  }
</style>

<div class="b1"></div>
<div class="b2"></div>

margin 边界叠加只会出现在普通文档流中,所以可以触发 BFC 来解决。
除此之外,也可以使用 padding 来代替 margin 或者增加 border 的值。

参考文章: 余白が消える margin の相殺って何?回避策を徹底解説

margin 的边界叠加发生在竖直方向上(左右方向上不会叠加)。兄弟 DOM 节点、父元素中的第一个子节点、以及最后一个尾节点都会产生 margin 边界叠加的现象。由于 CSS 早期主要用在文字、图片排版上,因此上下 margin 的叠加是符合预期效果的。

margin 边界叠加从结果上来看就是以最大的值为准。

<style>
  .b1 {
    width: 100px;
    height: 100px;
    margin-bottom: 30px;
  }
  // 最终两个 div 的 margin 为 40px,以最大的值为准。
  .b2 {
    width: 100px;
    height: 100px;
    margin-bottom: 40px;
  }
</style>

<div class="b1"></div>
<div class="b2"></div>

margin 边界叠加只会出现在普通文档流中,所以可以触发 BFC 来解决。
除此之外,也可以使用 padding 来代替 margin 或者增加 border 的值。

参考文章: 余白が消える margin の相殺って何?回避策を徹底解説

b2 应该是margin-top 吧

https://www.cnblogs.com/zhangmingze/articles/4664074.html

当两个垂直边界相遇时,它们将形成一个边界。这个边界的高度等于两个发生叠加的边界的高度中的较大者。
边界叠加的大多数问题可以通过添加透明边框或1px的补白来修复。

我们要搞清楚是为什么?应该先追求本质然后再来寻求解决之道
为什么要有margin塌陷,这看起来就是个bug,实际上翻看css的历史也不难理解,最开始的css就是为
普通的文本和图像来服务的。一块块段落直接用上下margin来间隔,如果没有上下塌陷,那么第一个元素距离父元素顶部,和最后一个元素距离父元素顶部的距离要小于其他兄弟元素的上下间隔,因为他们的间隔可是下面兄弟元素margin-top +上面兄弟元素 margin-bottom了,视觉上就很怪,于是乎就设计成了塌陷。 这样的话,margin塌陷会让兄弟元素的间隔以及兄弟元素和父元素的间隔是一样的。
具体的规范在CSS1中就有了
https://www.zhihu.com/question/20585258

今天看来这个特性好像有点bug,历史遗留了。

再后来CSS2.1规范里的BFC规范里有两条:

在BFC下,内部的Box会在垂直方向,一个接一个地放置
Box垂直方向的距离由margin决定。
在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘),即使存在浮动也是如此。
同一个BFC的两个相邻Box 的margin会发生重叠。
BFC的区域不会与float box重叠。
计算BFC的高度时,浮动元素也参与计算。
BFC和其他区块布局互不影响。

那么谁是BFC,满足以下几个条件之一:

根元素
overflow 不是visible
float 不是none
其他等等

margin的塌陷,其实就是BFC带来的问题

可以通过触发BFC来解决这个问题:

在一个BFC下两个元素的margin会重叠

解决方法:

  • 将两个元素分别放在不同的BFC下
  • 改成padding

margin边界叠加:当两个垂直边界相遇时,它们将形成一个边界,这个边界的高度等于两个发生叠加的边界的高度中的较大者。
解决方法:
1.外层padding
2.透明边框border:1px solid transparent;
3.绝对定位postion:absolute:
4.外层DIVoverflow:hidden;
5.内层DIV加float:left;display:inline;
6.外层DIV有时会用到zoom:1;

同一个盒子下的margin会重叠,取最大值
解决方法:形成BFC。
1放在不同的各自盒子
2父亲加overflow:hidden
3添加伪元素:clear:both
4父级添加边框

定义

  • 若是相邻块元素垂直外边距的合并,合并之后会取两者中的最大值。
  • 若是嵌套块元素垂直外边距的合并,合并会形成一个外边距,合并到父元素的外边距并取其中的最大值(margin塌陷)

解决方案

形成BFC

  • 使用padding代替,但是父盒子要减去相应的高度
  • 使用boder(透明)代替(不推荐,不符合书写规范,如果父盒子子盒子时有颜色的不好处理)
  • 给父盒子设置overflow:hidden(如果有溢出元素无法使用)
  • 给父盒子设置1px的padding
  • 给父盒子设置1px的透明border,高度减1px
  • 子盒子使用定位position
  • 子盒子浮动, 但是居中比较难以控制
  • 给子盒子设置display: inline-block
  • 子盒子上面放一个table标签

和前面bfc基本可以联系到一起

当两个垂直边界相遇时,它们将形成一个边界,这个边界的高度等于发生叠加的边界的高度中的较大者
解决方案:
1.外层padding
2.透明边框border:1pxsolidtransparent;
3.绝对定位postion:absolute:
4.外层DIVoverflow:hidden;
5.内层DIV 加float:left;display:inline;
6.外层DIV有时会用到zoom:1;

margin边界叠加(Margin Collapse)是指在一些特定情况下,相邻的两个或多个元素的外边距会合并(叠加)成一个较大的外边距的现象。这种现象可能会导致布局上的意外效果。

下面是一些常见的触发边界叠加的情况:

  1. 相邻的垂直外边距:当两个相邻元素的上下外边距相遇时,它们的外边距会合并成一个较大的外边距。

  2. 父元素与第一个/最后一个子元素的外边距:当父元素的上下外边距与其第一个或最后一个子元素的上下外边距相遇时,它们的外边距也会合并。

解决边界叠加的常见方法包括:

  1. 使用 padding 替代 margin:如果边界叠加是由于相邻元素的垂直外边距合并导致的,可以尝试使用 padding 来替代 margin,或者给其中一个元素添加一个较小的 padding 值。

  2. 使用 border 或 inline-block:在两个相邻元素之间添加一个边框或将它们设置为 inline-block 元素,可以防止边界叠加。

  3. 使用 clearfix:对于父元素与第一个/最后一个子元素的外边距合并问题,可以使用 clearfix 技术来解决。

  4. 使用 BFC(块级格式化上下文):将元素设置为 BFC 可以阻止其外边距与其他元素的外边距发生叠加。可以通过设置 overflow: hiddendisplay: inline-blockfloatposition: absolute 等属性来创建 BFC。

需要根据具体情况选择适合的解决方案来解决边界叠加问题。