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