Skip to content

BFC

BFC 区块格式化上下文(Block Formatting Context)是 Web 页面的可视 CSS 渲染的一部分,是块级盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

BFC 主要创建方式:

  • 浮动元素(即 float 值不为 none 的元素)。
  • overflow 值不为 visible 或 clip 的块级元素。
  • position 的值不为 static 或者 relative

BFC 解决什么?

格式化上下文影响布局,通常,我们会为定位和清除浮动创建新的 BFC,而不是更改布局

  • 包含内部浮动,防止父元素高度塌陷。
  • 排除外部浮动,防止覆盖兄弟元素和禁止文本环绕。
  • 阻止垂直方向外边距重叠(包含兄弟元素外边距重叠和父子元素外边距折叠)。

避免高度塌陷

查看代码
vue
<script setup lang="ts">
import { ref } from 'vue';
import Select from './select.vue';
const bfcStyle = ref('NoBFC');
</script>

<template>
	<div class="demo demo-1">
		<Select v-model:bfcStyle="bfcStyle" />
		<div class="parent" :class="{ bfc: bfcStyle !== 'NoBFC' }" :style="bfcStyle">
			<p>父元素空间: {{ bfcStyle }}</p>
			<div class="child fr">
				<p>子元素: float: left;</p>
			</div>
		</div>
	</div>
</template>

<style scoped lang="less">
@import './common.less';
.parent.bfc {
	border: 1px dashed green;
}
.parent {
	border: 1px dashed red;
	padding: 5px;
}
.child {
	padding: 5px;
	display: inline-block;
	width: fit-content;
	height: fit-content;
	line-height: 1.5;
	border: 1px dashed blue;
}
</style>
<script setup lang="ts">
import { ref } from 'vue';
import Select from './select.vue';
const bfcStyle = ref('NoBFC');
</script>

<template>
	<div class="demo demo-1">
		<Select v-model:bfcStyle="bfcStyle" />
		<div class="parent" :class="{ bfc: bfcStyle !== 'NoBFC' }" :style="bfcStyle">
			<p>父元素空间: {{ bfcStyle }}</p>
			<div class="child fr">
				<p>子元素: float: left;</p>
			</div>
		</div>
	</div>
</template>

<style scoped lang="less">
@import './common.less';
.parent.bfc {
	border: 1px dashed green;
}
.parent {
	border: 1px dashed red;
	padding: 5px;
}
.child {
	padding: 5px;
	display: inline-block;
	width: fit-content;
	height: fit-content;
	line-height: 1.5;
	border: 1px dashed blue;
}
</style>

避免高度塌陷: 将包含浮动元素的父元素设置为 BFC

避免外边距折叠(相邻元素)

查看代码
vue
<script setup lang="ts">
import { ref } from 'vue';
import Btn from '../btn/btn.vue';
import BFC from './bfc.vue';
const useBFC = ref(false);
</script>

<template>
	<div class="demo demo-1">
		<div class="btn-list">
			<span>请选择:</span>
			<Btn :active="useBFC" @click="useBFC = true" text="使用 BFC 包裹子元素二" />
			<Btn :active="!useBFC" @click="useBFC = false" text="不使用 BFC 包裹子元素二" />
		</div>

		<div class="parent">
			<div>父元素区域,外边距折叠仅与垂直方向有关</div>
			<div class="child">子元素一 :margin: 10px 0;</div>
			<BFC :useBFC="useBFC">
				<div class="child">子元素二 :margin: 10px 0;</div>
			</BFC>
			<div class="child">子元素三 :margin: 10px 0;</div>
		</div>
	</div>
</template>

<style scoped lang="less">
@import './common.less';
.parent {
	padding: 5px;
	border: 1px dashed red;
}
.child {
	padding: 5px;
	margin: 10px 0;
	border: 1px dashed blue;
}
</style>
<script setup lang="ts">
import { ref } from 'vue';
import Btn from '../btn/btn.vue';
import BFC from './bfc.vue';
const useBFC = ref(false);
</script>

<template>
	<div class="demo demo-1">
		<div class="btn-list">
			<span>请选择:</span>
			<Btn :active="useBFC" @click="useBFC = true" text="使用 BFC 包裹子元素二" />
			<Btn :active="!useBFC" @click="useBFC = false" text="不使用 BFC 包裹子元素二" />
		</div>

		<div class="parent">
			<div>父元素区域,外边距折叠仅与垂直方向有关</div>
			<div class="child">子元素一 :margin: 10px 0;</div>
			<BFC :useBFC="useBFC">
				<div class="child">子元素二 :margin: 10px 0;</div>
			</BFC>
			<div class="child">子元素三 :margin: 10px 0;</div>
		</div>
	</div>
</template>

<style scoped lang="less">
@import './common.less';
.parent {
	padding: 5px;
	border: 1px dashed red;
}
.child {
	padding: 5px;
	margin: 10px 0;
	border: 1px dashed blue;
}
</style>

避免外边距折叠: 相邻元素外边距折叠,给其中一个元素添加一个 BFC 容器

避免外边距折叠(父子元素)

如果块级父元素中,不存在上边框上内补inline content清除浮动这四条属性,
(对于上边框和上内补,也可以说,当上边距及上内补宽度为 0 时),
那么这个块级元素其第一个子元素就会发生上边距折叠
这个折叠之后的值在这里取的就是两者之间的最大值

查看代码
vue
<script setup lang="ts">
import { ref } from 'vue';
import Btn from '../btn/btn.vue';
const useBFC = ref(false);
</script>

<template>
	<div class="demo demo-3">
		<div class="btn-list">
			<span>请选择:</span>
			<Btn :active="useBFC" @click="useBFC = true" text="设置父元素为 BFC 容器" />
			<Btn :active="!useBFC" @click="useBFC = false" text="不设置父元素为 BFC 容器" />
		</div>

		<div class="test">参照元素:height: 30px;</div>

		<div class="parent" :class="{ bfc: useBFC }">
			<p class="child">子元素 :margin-top: 30px;</p>
			<p>父元素 : margin-top: 10px;</p>
			<p>父元素 : {{ useBFC ? '是' : '不是' }} BFC</p>
		</div>
	</div>
</template>

<style scoped lang="less">
@import './common.less';
.parent.bfc {
	overflow: hidden;
	border: 0 solid green;
	border-width: 0 1px 1px;
	box-shadow: inset 0px 1px 0 0 green;
}
.test {
	height: 30px;
	border: 1px solid yellow;
}
.parent {
	display: block;
	margin-top: 10px;
	padding: 0;
	border: 0 solid red;
	border-width: 0 1px 1px;
	box-shadow: inset 0px 1px 0 0 red;
}
.child {
	margin-top: 30px !important;
	border: 1px dashed blue;
}
</style>
<script setup lang="ts">
import { ref } from 'vue';
import Btn from '../btn/btn.vue';
const useBFC = ref(false);
</script>

<template>
	<div class="demo demo-3">
		<div class="btn-list">
			<span>请选择:</span>
			<Btn :active="useBFC" @click="useBFC = true" text="设置父元素为 BFC 容器" />
			<Btn :active="!useBFC" @click="useBFC = false" text="不设置父元素为 BFC 容器" />
		</div>

		<div class="test">参照元素:height: 30px;</div>

		<div class="parent" :class="{ bfc: useBFC }">
			<p class="child">子元素 :margin-top: 30px;</p>
			<p>父元素 : margin-top: 10px;</p>
			<p>父元素 : {{ useBFC ? '是' : '不是' }} BFC</p>
		</div>
	</div>
</template>

<style scoped lang="less">
@import './common.less';
.parent.bfc {
	overflow: hidden;
	border: 0 solid green;
	border-width: 0 1px 1px;
	box-shadow: inset 0px 1px 0 0 green;
}
.test {
	height: 30px;
	border: 1px solid yellow;
}
.parent {
	display: block;
	margin-top: 10px;
	padding: 0;
	border: 0 solid red;
	border-width: 0 1px 1px;
	box-shadow: inset 0px 1px 0 0 red;
}
.child {
	margin-top: 30px !important;
	border: 1px dashed blue;
}
</style>

避免外边距折叠: 父子元素,给父元素设置 BFC

清除浮动元素文本环绕和覆盖

清除浮动元素文本环绕: 给非浮动元素设置 BFC

查看代码
vue
<script setup lang="ts">
import { ref } from 'vue';
import Btn from '../btn/btn.vue';
import Screen from '../screen/screen.vue';

const useBFC = ref(false);
</script>

<template>
	<div class="demo demo-3">
		<div class="btn-list">
			<span>请选择:</span>
			<Btn :active="useBFC" @click="useBFC = true" text="设置文本元素为 BFC 容器" />
			<Btn :active="!useBFC" @click="useBFC = false" text="不设置文本元素为 BFC 容器" />
		</div>
		<Screen class="parent" :min-height="120">
			<div class="child fl">子元素 :float: left;</div>
			<div class="child" :class="{ bfc: useBFC }">
				这是一个浮动元素后面的文本内容(有斑马线背景)。在没有创建BFC的情况下,这段文本可能会被浮动元素覆盖。<br />
				这是一个浮动元素后面的文本内容(有斑马线背景)。在没有创建BFC的情况下,这段文本可能会被浮动元素覆盖。
			</div>
		</Screen>
	</div>
</template>

<style scoped lang="less">
@import './common.less';
.child.bfc {
	overflow: hidden;
	border: 0 solid green;
	border-width: 0 1px 1px;
	box-shadow: inset 0px 1px 0 0 green;
}
.parent {
	display: block;
	color: black;
}
.child {
	border: 1px dashed blue;
}
.child:not(:first-child) {
	background-image: repeating-linear-gradient(rgba(0, 0, 0, 0.1) 0 2px, transparent 0 6px);
}
</style>
<script setup lang="ts">
import { ref } from 'vue';
import Btn from '../btn/btn.vue';
import Screen from '../screen/screen.vue';

const useBFC = ref(false);
</script>

<template>
	<div class="demo demo-3">
		<div class="btn-list">
			<span>请选择:</span>
			<Btn :active="useBFC" @click="useBFC = true" text="设置文本元素为 BFC 容器" />
			<Btn :active="!useBFC" @click="useBFC = false" text="不设置文本元素为 BFC 容器" />
		</div>
		<Screen class="parent" :min-height="120">
			<div class="child fl">子元素 :float: left;</div>
			<div class="child" :class="{ bfc: useBFC }">
				这是一个浮动元素后面的文本内容(有斑马线背景)。在没有创建BFC的情况下,这段文本可能会被浮动元素覆盖。<br />
				这是一个浮动元素后面的文本内容(有斑马线背景)。在没有创建BFC的情况下,这段文本可能会被浮动元素覆盖。
			</div>
		</Screen>
	</div>
</template>

<style scoped lang="less">
@import './common.less';
.child.bfc {
	overflow: hidden;
	border: 0 solid green;
	border-width: 0 1px 1px;
	box-shadow: inset 0px 1px 0 0 green;
}
.parent {
	display: block;
	color: black;
}
.child {
	border: 1px dashed blue;
}
.child:not(:first-child) {
	background-image: repeating-linear-gradient(rgba(0, 0, 0, 0.1) 0 2px, transparent 0 6px);
}
</style>

清除浮动元素文本环绕: 给非浮动元素设置 BFC

༼ つ/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿◕ _◕ ༽つ/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿ ̿̿