CSS中的BFC机制

2024-03-06 19:18
文章标签 css 机制 frontend bfc

本文主要是介绍CSS中的BFC机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 什么是BFC

块格式化上下文BFC(Block Formatting Context,BFC) 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。以上内容摘自MDN,其实通俗来讲BFC就是一个独立的布局环境,BFC中的元素布局不受外部元素的影响,也不会影响到外部元素。

2 如何触发BFC

其实在日常开发中经常会主动触发BFC:

  1. 给元素设置浮动(float: left | right
  2. 给元素设置脱离文档流的定位(position: absolute | fixed
  3. 给元素设置内容溢出(overflow: hidden | scroll
  4. 给元素设置弹性布局(display: flex

以上列出的都是常见的几种,更多触发BFC的方式可查阅文档MDN-BFC。除了主动触发BFC,其实每个HTML文档中都会被动触发BFC,因为其根元素html本身就会形成一个BFC,可以理解为页面中的所有元素都存在与某个BFC环境下。

3 BFC的特性

3.1 BFC内部依然遵循元素定位规则

在CSS中,元素定位规则分为以下三种:

  1. 普通文档流:元素按照从上至下,从左至右的顺序排列,但元素又分行内元素和块级元素,其排列方式有所不同:
    1. 行内元素:水平排列,直到水平方向占满一行后再另起一行排列。
    2. 块级元素:垂直排列,每一个块级元素都会独自占用一行。
  2. 浮动流:设置浮动的元素会向左或向右浮动,直到碰到父级元素或其他浮动的元素,需要注意的是,设置浮动的元素只是半脱离文档流。
  3. 脱离文档的定位流:当定位设置为absolute绝对定位或fixed固定定位时,元素会完全脱离文档流,元素的位置就是定位时设置的位置,其布局不会受其他元素的影响,也不会影响到其他元素。

BFC内部依然遵循元素定位规则这句话很好理解,前面提到根元素html本身会形成一个BFC,所以其内部自然遵循元素定位规则。

3.2 BFC内部相邻元素垂直外边距合并

属于同一个BFC的内部两个相邻的元素的垂直外边距会发生合并,这个特性在li标签下格外明显,举个例子:

<ul><li>JavaScript</li><li>Python</li><li>C++</li><li>Java</li><li>Golang</li>
</ul>
ul {width: 200px;
}li {list-style: none;border: 3px solid pink;border-radius: 3px;margin: 10px 0px; /* 关键代码:为li标签设置了10px的上下外边距 */text-align: center;
}

在CSS中为li标签设置了上下10px的外边距,理论上每个li标签在垂直距离上应该相距20px,但结果却是每个li标签在垂直距离上只相距10px
image.pngimage.pngimage.png
这就是发生了外边距合并。

3.3 不同BFC的相邻元素不会外边距合并

要解决3.2节中的外边距合并问题,可以将每个被合并的元素都放在一个单独的BFC环境下,这样就不会发生外边距合并,修改代码如下,将每个li标签用一个div标签包裹:

  <ul><div><li>JavaScript</li></div><div><li>Python</li></div><div><li>C++</li></div><div><li>Java</li></div><div><li>Golang</li></div></ul>

再让每个div标签触发BFC机制,这里选用最为常用的overflow: hidden;方式:

    ul div {overflow: hidden;}

效果如下:
image.pngimage.png
不难发现两个li标签的距离为20px,这样就通过BFC机制解决了外边距合并问题。

3.4 BFC中元素的margin-box的左边与子元素的border-box左边相接

该特性的完整描述为“每个元素的margin-box的左边会与包含块border-box的左边相接触(对于从左到右的格式化,否则相反),即使存在浮动也会如此。”这句话晦涩难懂,先来解释一下什么叫margin-box什么叫border-box,这两个词都来源于盒模型:
image.png
本文中仅讨论W3C标准盒子模型,可以发现一个盒子由内至外分别为contentpaddingbordermargin四个部分组成,而每一个部分对应着content-boxpadding-boxborder-boxmargin-box

3.4.1 浮动的元素

举个例子:

<div class="box1"><div class="box2"></div>
</div>
.box1 {width: 500px;height: 500px;background-color: red;overflow: hidden; /* 触发BFC */
}
.box2 {width: 300px;height: 300px;background-color: blue;float: left; /* 添加左浮动 */
}

效果如下:
image.png
图中box1box2只设置了widthheight,未设置marginborderpadding,此时参照的是父元素的最外层margin-box,所以box2box1直接相接。但当父元素拥有paddingborder时,此时参照的是padding-boxborder-box,如下图是设置了border的效果:
image.png
如下图是给box1设置了padding的效果:
image.png
如下图是给box1即设置了border也设置了padding的效果:
image.png

3.4.2 定位的元素

依然采用3.4.1节中的例子,将box2从左浮动改为绝对定位position: absolute;并设置left: 0;top: 0;

.box1 {width: 500px;height: 500px;background-color: red;overflow: hidden; /* 触发BFC */border: 30px solid pink;padding: 30px;position: relative;
}
.box2 {width: 300px;height: 300px;background-color: blue;position: absolute;left: 0;top: 0;
}

box1不设置marginborderpadding的情况下如下所示,其结果与浮动的元素相同:
image.png
box1设置border后效果如下所示,其结果也与浮动的元素相同:
image.png
box1设置padding后的效果如下所示,此时效果就与浮动的元素不同了,定位的元素会直接“忽视”padding的存在,直接box1的左边缘相接:
image.png
box1即设置border又设置padding的效果如下,可以发现box1padding依然被“忽视”了,直接与border-box相接:
image.png

3.4.3 总结

  • BFC内元素为浮动的情况下:参照的是content-box
  • BFC内元素为定位的情况下:参照的是padding-box

3.5 BFC计算高度时包括浮动元素

该特性是用于清除浮动的方法之一,给父元素添加overflow: hidden属性触发BFC机制即可,详细请阅读CSS浮动和清除浮动中的4.3节。

3.6 BFC的区域不会与浮动元素发生重叠

该特性常用于两栏自适应布局,即左边固定宽度,右边宽度自适应,如下图所示:
image.png
实现方式如下:

* {margin: 0;padding: 0;
}html,
body {width: 100%;height: 100%;
}.left {width: 200px;height: 100%;background: red;float: left;
}.right {height: 100%;background: blue;overflow: hidden;
}
<div class="left"></div>
<div class="right"></div>

4 BFC的应用场景

4.1 清除浮动

见3.5节

4.2 两栏自适应布局

见3.6节

4.3 消除边距合并

见3.3节

这篇关于CSS中的BFC机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/781052

相关文章

vue, 左右布局宽,可拖动改变

1:建立一个draggableMixin.js  混入的方式使用 2:代码如下draggableMixin.js  export default {data() {return {leftWidth: 330,isDragging: false,startX: 0,startWidth: 0,};},methods: {startDragging(e) {this.isDragging = tr

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

js+css二级导航

效果 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

vue+el国际化-东抄西鉴组合拳

vue-i18n 国际化参考 https://blog.csdn.net/zuorishu/article/details/81708585 说得比较详细。 另外做点补充,比如这里cn下的可以以项目模块加公共模块来细分。 import zhLocale from 'element-ui/lib/locale/lang/zh-CN' //引入element语言包const cn = {mess

vue同页面多路由懒加载-及可能存在问题的解决方式

先上图,再解释 图一是多路由页面,图二是路由文件。从图一可以看出每个router-view对应的name都不一样。从图二可以看出层路由对应的组件加载方式要跟图一中的name相对应,并且图二的路由层在跟图一对应的页面中要加上components层,多一个s结尾,里面的的方法名就是图一路由的name值,里面还可以照样用懒加载的方式。 页面上其他的路由在路由文件中也跟图二是一样的写法。 附送可能存在

vue+elementUI下拉框联动显示

<el-row><el-col :span="12"><el-form-item label="主账号:" prop="partyAccountId" :rules="[ { required: true, message: '主账号不能为空'}]"><el-select v-model="detailForm.partyAccountId" filterable placeholder="

vue+elementui分页输入框回车与页面中@keyup.enter事件冲突解决

解决这个问题的思路只要判断事件源是哪个就好。el分页的回车触发事件是在按下时,抬起并不会再触发。而keyup.enter事件是在抬起时触发。 so,找不到分页的回车事件那就拿keyup.enter事件搞事情。只要判断这个抬起事件的$event中的锚点样式判断不等于分页特有的样式就可以了 @keyup.enter="allKeyup($event)" //页面上的//js中allKeyup(e

vue子路由回退后刷新页面方式

最近碰到一个小问题,页面中含有 <transition name="router-slid" mode="out-in"><router-view></router-view></transition> 作为子页面加载显示的地方。但是一般正常子路由通过 this.$router.go(-1) 返回到上一层原先的页面中。通过路由历史返回方式原本父页面想更新数据在created 跟mounted