BFC与margin-collapse(外边距合并)

本文详细介绍了CSS中BFC的概念、布局规则及触发方式,并通过实例解析BFC如何解决自适应布局、清除浮动及防止margin重叠等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是BFC?

BFC即Block Formatting Context,直译为“块级格式化上下文”,它是W3C CSS2.1规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。它其实就是一个看不见摸不着的区域,不管BFC元素内部子元素怎么变化,都不会影响外部的元素。常用来解决如清除浮动、防止margin重叠等问题。

二、BFC布局规则

  • 内部的Box会在垂直方向,一个接一个地放置;
  • Box垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠;
  • 每个元素的margin-box的左边,与包含border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此;
  • BFC的区域不会与float box重叠;
  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
  • 计算BFC的高度时,浮动元素也参与计算。

三、怎样触发BFC?

  • 根元素(html);
  • float属性不为none;
  • position为absolute或fixed;
  • display为inline-block, table-cell,table-caption,flex,inline-flex;
  • overflow不为visible

四、BFC的作用与原理

1. 自适应两栏布局

代码:

<style>
    body {
        width: 300px;
        position: relative;
    }
 
    .aside {
        width: 100px;
        height: 150px;
        float: left;
        background: #f66;
    }
 
    .main {
        height: 200px;
        background: #fcc;
    }
</style>
<body>
    <div class="aside"></div>
    <div class="main"></div>
</body>

页面:



根据BFC布局规则第三条:

每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。

因此,虽然存在浮动的元素aside,但main的左边依然会与包含块的左边相接触。

根据BFC布局规则第四条:

BFC的区域不会与float box重叠。

我们可以通过通过触发main生成BFC,来实现自适应两栏布局。

    .main {
        overflow:hidden;
    }

当触发main生成BFC后,这个新的BFC不会与浮动的aside重叠。因此会根据包含块的宽度,和aside的宽度,自动变窄。效果如下:


2. 清除内部浮动

代码:

<style>
    .par {
        border: 5px solid #fcc;
        width: 300px;
    }
 
    .child {
        border: 5px solid #f66;
        width:100px;
        height: 100px;
        float: left;
    }
</style>
<body>
    <div class="par">
        <div class="child"></div>
        <div class="child"></div>
    </div>
</body>

页面:


父元素内部的子元素浮动时,父元素的高度会发生塌陷,这是一个很常见的问题。

根据BFC布局规则第六条:

计算BFC的高度时,浮动元素也要参与计算。

为达到清除内部浮动,可以通过触发父元素par生成BFC,在计算par高度时,par内部的浮动元素child也会参与计算。

代码:

    .par {
        overflow: hidden;
    }

效果如下:

父元素高度被重新撑开。

3. 防止垂直margin重叠

在CSS中,相邻的两个盒子(可能是兄弟关系也可能是祖先关系)的外边距可能会发生重叠,需要注意的是,重叠只发生在垂直方向,水平方向不会发生。重叠的结果是:

  • 两个相邻的外边距都是正数时,重叠结果是它们两者之间的较大值;
  • 两个相邻外边距都是负数时,重叠结果是两者绝对值的较大值;
  • 两个外边距一正一负时,重叠结果是两者的相加的和。

代码:

<style>
    div {
        color: #f55;
        background: #fcc;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
    }
</style>
<body>
    <div>Haha</div>
    <div>Hehe</div>
</body>

页面效果:

两个div之间的距离为100px,发生了margin重叠。根据BFC布局规则第二条:

Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。

对于这种两个兄弟元素垂直方向的margin重叠,最简单的解决方法就是不要同时既设置一个元素的margin-bottom又设置另一个元素的margin-top,将它们之间的margin值统一设置到一个元素的margin-top或margin-bottom上。

当然这里讲到BFC,自然要提用BFC的方法来解决。我们可以通过在其中一个div外面包裹一层容器,并触发该容器生成一个BFC,那么这两个div就不属于同一个BFC,自然就不会发生margin重叠了。

代码:

<style>
    .one {
        color: #f55;
        background: #fcc;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
    }
    .wrap {
       overflow: hidden;    
    }
</style>
<body>
    <div class="one">Haha</div>
    <div class="wrap">
    	<div class="one">Hehe</div>
    </div>
</body>

页面效果:


还有一种情况是嵌套关系的Box。

代码:

    <style>
        body {
            font-family: 'Microsoft Yahei';
        }
        .par {
            background: #f66;
            width: 300px;
            height: 200px;
        }
        .child {
            color: #f55;
            background: #fcc;
            width: 200px;
            line-height: 100px;
            text-align:center;
            margin-top: 50px;
        }
    </style>
    <body>
        <div class="par">
            <div class="child">child</div>
        </div>
    </body>

页面效果:


我们希望的是里面的盒子与包裹它的父盒子之间有一定的间距,但是很不幸的是外层div也跟着一起移下来了,它们俩还是紧紧地贴在一起。

根据BFC规则第五条:

BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之亦然。

这种情况同样可以通过触发父元素产生一个BFC来解决,轻松达到我们想要的结果。

代码:

    <style>
        body {
            font-family: 'Microsoft Yahei';
        }
        .par {
            background: #f66;
	    width: 300px;
	    height: 200px;
	    overflow: hidden;
	}
	.child {
            color: #f55;
            background: #fcc;
            width: 200px;
            line-height: 100px;
            text-align:center;
            margin-top: 50px;
	}
    </style>
    <body>
        <div class="par">
            <div class="child">child</div>
        </div>
    </body>

页面效果:


当然我们还可以通过直接设置父盒子的padding值来解决。同时我们还可以通过给父元素设置一个border,也可以达到我们想要的效果。

五、总结

其实以上的几个例子都体现了BFC布局的第五条规则,即:

BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之亦然。

因为BFC内部的元素和外部的元素绝对不会互相影响,因此,当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄而不与浮动有重叠。同样的,当BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是同样的道理。


参考链接:

http://www.cnblogs.com/lhb25/p/inside-block-formatting-ontext.html

http://www.zhangxinxu.com/wordpress/2015/02/css-deep-understand-flow-bfc-column-two-auto-layout/

http://www.w3cplus.com/css/understanding-bfc-and-margin-collapse.html

http://www.cnblogs.com/tanxu/p/3500152.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值