外边距重叠
外边距重叠(英文margin collapse,MDN 的解释如下:
块的顶部和底部边距有时合并(折叠)为单个边距,其大小是单个边距(或者是单个边距中最大的一个,如果它们相等的话),这种行为称为边距折叠。注意,浮动和绝对定位元素的边距永远不会崩溃。
这种情况并不是浏览器的bug,而是为某些情景而设计的,如下:
<section class="design">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam harum
volutes ulema, quia venial sung in maiores option laboriously, harum
minus veritas destruct selectus repellent's eacute nostrum vitae! Amet,
alias.
</p>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam harum
volutes ulema, quia venial sung in maiores option laboriously, harum
minus veritas destruct selectus repellent's eacute nostrum vitae! Amet,
alias.
</p>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam harum
volutes ulema, quia venial sung in maiores option laboriously, harum
minus veritas destruct selectus repellent's eacute nostrum vitae! Amet,
alias.
</p>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam harum
volutes ulema, quia venial sung in maiores option laboriously, harum
minus veritas destruct selectus repellent's eacute nostrum vitae! Amet,
alias.
</p>
</section>
为了让段落分明,一般会给上margin
p{
text-indent: 2em;
margin: 1.7em 0;
}
当你打开控制台查看p标签的时候,会发现他们间隔是一样的,也就是为了这种情况而设计的,不过也产生了一种生产环境经常遇到的「bug」,叫margin collapse,也就是外边距重叠了
外边距重叠的三种情况
- 相邻的两个块级盒子,在第一个盒子设置了margin-bottom后第二个盒子设置了margin-top
- 三个层级的块盒子,最后一个层级的盒子相对于第二个层级盒子设置margin-top
- 三个同级对块盒子,中间对盒子内容为空,想设置margin-top和margin-bottom级来为上下两个盒子制造空隙,将发生外边距崩塌
💡 注意,会造成外边距重叠的情况,只有垂直方向上的块级盒子
解决方案
- 子绝父相
- inline-block不会造成外边距崩塌,所以可以改成inline-block(改成inline-block后要记得设置宽高)
- 设置position为relative,然后用top来代替margin-top
- 设置float后再来margin-top
- 不能设置外边距,那就改成内边距
- 添加边框,设置边框厚度
- 创建BFC(overflow:hidden会触发创建BFC)
BFC(block formating context 块级格式化上下文)
前端的布局有三种:
- 普通流(也是浏览器默认的)
- 块级格式化上下文(BFC,block formatting context)。
- 内联格式化上下文(IFC,inline formatting context)。
- 弹性格式化上下文(FFC,flex formatting context),在 CSS3 中定义。
- 栅格格式化上下文(GFC,grid formatting context),在 CSS3 中定义。
- flow布局
- 绝对定位
后两个都会脱离文档流,接下来要讲的BFC,就是属于普通流一种
是的:BFC会形成独立的渲染区域⚠️,使得内部元素的渲染不会影响到外界
清除浮动
![goI4GD](https://oshino.oss-cn-shenzhen.aliyuncs.com/uPic/goI4GD.png)//主要代码,为了方便看到效果,给了背景色 // rgb(228, 99, 48) <div class="content_box"> <img src="./img/selfie.jpg"/> // rgb(168, 218, 235) <div class="statement"> <p>...</p> <p>...</p> </div> </div>
一般在情况下,都是一边产品图,一边文字说明,这里我们让图片设置为 flow(当然还有其他解决方案,这里是为了方便举例子,其他就不扩展了)
可以看到flow设置为flow之后,img脱离了文档流,content_box的大小变成只靠两个p来支撑,我们需要的是content_box是img的大小也影响着content_box,这种情况下就可以给content_box的css添加一个属性来触发BFC,因为为了在此情况下不要有太大改变,一般我们使用display:flow-root或者contain:layout(加黑是因为你也可以使用其他属性来触发BFC,比如overflow:hidden)
![ogo3A0](https://oshino.oss-cn-shenzhen.aliyuncs.com/uPic/ogo3A0.png).content_box { display: flow-root; }
这样就可以清除掉img的 flow:left 所脱离文档流从而影响content_box的整体渲染
包裹浮动
还是上面👆的例子,打开控制台,元素里查看以下statement盒子
看到这里的p标签还是占着一整行,这样在我们后面调整statement盒子使得文字不要那么贴近图片的时候是很不方便的,比如添加padding-left(ps:调整p的padding/margin也一样)
我们也可以给statement添加一个BFC,让statement成为一个独立渲染的区域不影响外部
再刷新一下.statement{ padding-left: 2em; display: flow-root; }
这样就可以使元素(statement)包裹着浮动元素了
解决margin collapse
还是上面的例子,p标签太近了,我们添加个属性margin
![005UbvFEgy1h98iruk3dhg30go08pttp](https://oshino.oss-cn-shenzhen.aliyuncs.com/uPic/005UbvFEgy1h98iruk3dhg30go08pttp.gif)p{ margin: 1.7em 0; }
可以看到这里发生了一开始我们提到的外边距重叠(margin collapse),我也提到了这是专门这样子设计的,不是bug,怎么解决呢,没错,上面解决方案的第七个,可以创建一个BFC
<div class="statement"> <div> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam harum volutes ulema, quia venial sung in maiores option laboriously, harum minus veritas destruct selectus repellent's eacute nostrum vitae! Amet, alias. </p> </div> <div> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam harum volutes ulema, quia venial sung in maiores option laboriously, harum minus veritas destruct selectus repellent's eacute nostrum vitae! Amet, alias. </p> </div> </div>
给p套一个div,让这个div形成一个BFC独立渲染.statement div{ display: flow-root; }
这样就可以防止外边距重叠了
创建BFC有以下(用得比较多得加黑了
<html/>
根元素- 设置了float属性且值不为none的元素
- position:absolute、fixed的元素
- 设置了display:inline-block/ flow-root的元素
- 设置了display:table-的元素(例如table-cell、table-caption、table-row*等)
- 设置了overflow值不为visible和clip以外的元素(例如:overflow:hidden)
- 设置contain的元素(layout | content | paint)
- flex 和grid布局的子元素(非flex和grid布局容器本身)
多列布局,设置了column-count的元素,或设置了column-span:all的元素
code inline
.
提示:display: flow-root
,contain: layout
等是无副作用的,可在不影响已有布局的情况下触发 BFC,所以会用的比较多 a