外边距合并 margin collapse
在块级盒子中,上下外边距可能会出现折叠,即合并成值比较大的那个外边距,这种情况叫外边距合并。注意,指的是垂直方向上的margin。
一、出现外边距合并的情况
1、相邻元素之间
2、父元素与其第一个或最后一个子元素之间
- 父元素的上外边距和第一个子元素的上外边距
- 父元素的下外边距和最后一个子元素的下外边距
3、空元素自己的上下外边距会合并
举一个例子:
<p style="margin-bottom: 0px;">段落1</p>
<div style="margin-top: 50px; margin-bottom: 5px;"></div>
<p style="margin-top: 0px;">段落2</p>
这时候段落1和段落2的距离是50px.
如果将段落1或2的参数改为其他数值,这时候又会发生相邻元素(即p与div)的外边距合并。
注意:
- 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
- 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
- 两个外边距一正一负时,折叠结果是两者的相加的和。
- 即使某一外边距为0,以上规则仍然适用。因此就算父元素的外边距是0,第一个或最后一个子元素的外边距仍然会“溢出”到父元素的外面【理解!】
二、避免外边距合并
1、三种情况都适用的方法
-
静态文档流元素才会合并,因此可以设置为 float / position: absolute,包括:
- 相邻的两个相邻的盒模型中,如果其中的一个是浮动的,垂直margin不会被折叠
- 一个浮动的盒模型和它的子元素之间也不会折叠
-
设置为 display: inline-block
2、针对相邻元素的合并
- 包裹一个div,设置overflow:hidden
3、针对父元素与子元素的合并
- 创建BFC
- 父元素设置 overflow:auto
- 父元素设置 overflow: hidden
- 坏处:内容溢出时会被隐藏。
- 由于在IE比较低版本的浏览器中使用overflow:hidden;是不能达到这样的效果,因此需要加上 zoom:1;
- 注意,使用overflow的方法只会解决父元素和子元素之间,在子元素之间还是会存在合并。
- 通过设置子元素或者父元素的宽高\添加内容\padding\border等将它们的margin隔开
4、针对空元素合并
通过设置border\padding\height等
BFC
在外边距合并问题上我们常常会看见BFC。以上提到的方法很多也是创建了BFC。那么问题来了,BFC到底是什么?在这个问题之前,我们需要先了解盒子模型、
Need to know first
1、Formatting Context
Formatting Context是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及各其他元素的关系和相互作用。
最常见的是BFC(Block Formatting Context)和IFC(Inline Formatting Context)(css2.1),在css3中增加了GFC(GridLayout Formatting Context)、FFC(Flex Formatting Context)。
2、普通流(Normal Flow)
在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行, 除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。
一、BFC是什么
BFC:块格式化上下文(Block Formatting Context)
【MDN】是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域
【MDN】浮动定位和清除浮动时只会应用于同一个BFC内的元素。浮动不会影响其它BFC中元素的布局,而清除浮动只能清除同一BFC中在它前面的元素的浮动。外边距折叠(Margin collapsing)也只会发生在属于同一BFC的块级元素之间
其实BFC属于普通文档流,但是BFC是一个独立的容器,好比一个个大箱子,各箱子之间互不影响,箱子里面的东西(内部元素)相互影响,因此也就可以通过创建BFC来解决元素的外边距合并问题。
BFC的其他特性:
- 内部的box会在垂直方向,一个接一个地放置
- 可以包含浮动元素,因此可用来解决因浮动造成的高度塌陷。在计算BFC的高度时,要考虑BFC所包含的所有元素,包括浮动元素。
- BFC的区域不会与浮动盒子重叠(解决浮动元素文字环绕问题)
- BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘)
二、常见的创建BFC方法
- 根元素
- float: 不为”none” (如:float:left/right)
- overflow: 不为”visible”(如:overflow:hidden)
- display: table-cell / table-caption / inline-block / flex / inline-flex
- position: 不为 “static” 或 “relative(如:position:absolute)
三、作用
1、解决外边距合并
就是我们在上面讲到的方法啦,原理就是使外边距合并的对象属于不同的BFC,这样就不会相互影响了。
2、创建自适应两栏布局
假设有两个div,floatbox 和 normalbox,floatbox 设置左边浮动。
此时normalbox会和floatbox在左边重叠。
通过特性:BFC的区域不会与浮动盒子重叠,可以给floatbox创建BFC,使它们分离,实现自适应两列布局。
但是这时候floatbox和normalbox还挨在一起,可以通过设置margin或padding分开。最好是设置在floatbox上,设置在normalbox上的值需要很大才能达到我们想要的效果。并且,如果设置在normalbox上,就和流体块的自适应布局无异了。(一边固定宽度,float或absolute,另一边通过margin或padding退让出距离)
推荐:张鑫旭:CSS深入理解流体特性和BFC特性下多栏自适应布局,大佬写的蛮生动哈哈。
3、清除内部浮动,解决父元素高度塌陷
当子元素浮动,父元素没有其它内容时,父元素会出现高度坍塌。
这时候给父元素建立BFC(eg.overflow: hidden;),由于特性: BFC会包含浮动元素,从而让父元素包裹住浮动元素,解决了高度塌陷的问题。
IE7及以下版本不支持BFC,但是它有自己私有的属性hasLayout,可以达到相同的效果,这个下次再整理笔记。(为什么IE总是搞特殊!!!)
经过最近的学习先整理到这,以后有更深的理解了再来更新。
有些用语和细节可能不够准确,欢迎指正~