CSS中关于定位及BFC中的易错点

提及BFC,就必须先了解一下CSS文档流中的定位机制,并且这部分说简单也简单,但却有个坑有可能误导咱们,特在本文做出解释。html

1、文档流中的定位机制

1. 三种基本方式

CSS有三种基本定位机制,我想大多数朋友都掌握了,在此简要概述一下(不浪费时间):面试

  1. 普通流(或称常规流):CSS默认的定位方式,触发方式包括为position: static/relative,且float:none
  2. 浮动:浮动脱离普通流,能够左右移动,直到它的外边框边缘碰到包含框或另外一个浮动框的边缘,触发方式基本就是float:left/top等。
  3. 绝对定位:盒子脱离普通流,不影响普通流上其余元素的布局

2. 注意事项

因此,此时大部分初学者都会结合现实世界感受到这三种流的立体感就是以下图所示的这样: bash

image

这里我想说的是,上图这种表达方式不能说是彻底正确,虽然层级明确了,但这会给初学者带来错误的理解:浮动元素既然已经玩飘了,且普通流中的div也不会再给它留地方了,那浮动元素对普通应该就完全没影响了吧? 固然不是! 直接上个小例子看看(多余上色之类的代码去掉了):布局

<body>
  <div class='parent'>
    <div class='child1'>
       Child1
    </div>
	<div class='child2'>
	    冷咖啡离开了杯垫
		我忍住的情绪在很后面
	</div>
  </div>
</body>
<style>
.parent {
  width:400px;
  min-height:100px;
}
.child1 {
  width:50px;
  height:50px;
}
.child2 {
  width:100px;
  height:100px;
}
</style>
复制代码

效果以下:post

image

好的,那接下来,按照咱们的想法,把child1设为浮动,此时它就应该脱离普通流,且普通流中的元素再也不考虑它的位置了,child1添加float:left后以下:学习

image

咦!child1确实感受浮动了,child2也确实绝不客气的把child1本来的位置给顶替了, 可child2里面的元素是咋回事?为何像躲摔倒的老太太同样躲避child1了呢? 这就是我想提醒朋友们必定要注意的地方。下面看看解释:flex

float起初被设计出来的初衷实际上是为了实现报纸上的那种文字环绕图片的效果,就像咱们上例这种普通流中的文字环绕在child1的周围。但以后你们才发现结合float + div 能够实现必定的网页布局,因此,这是浮动的特性。即浮动只是脱离了文档流,即不会按照你的设计而进行布局,就算它在任何位置上那也是和文档流中的其余内容是是平级关系的,咱们在使用浮动时,基本上就考虑它的布局定位就好了,不要以为它完全飘了,它的影响还在。ui

好了,这个坑帮不知道的朋友解决了,接下来就好理解BFC了。spa

2、BFC探索之路

你可能在不知道BFC是啥玩意的前提下却知道解决子div浮动而形成父div塌陷的一个经典的办法就是给父div设置overflow:hidden,但要是面试官问你为啥,你可能就歇菜了,别问我怎么知道,我曾经就是那个菜鸡...,因此,了解了BFC,你就知道为啥了。设计

1. BFC概念

BFC(Block Formatting Context,块格式上下文)是Web页面的可视化CSS渲染的一部分,而且有自身的一套渲染规则,它决定了其子元素如何定位,以及和其余元素的关系和相互做用。

2. BFC特色

具备BFC特性的元素能够当作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,而且BFC具备普通容器所没有的一些特性。不少好的文章罗列的内容有:

  1. 内部的box会在垂直方向,从顶部开始一个接一个地放置;
  2. box垂直方向的距离由margin决定,属于同一个BFC的两个相邻的box的垂直方向的margin会发生叠加;
  3. 在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)。对于从右到左的格式来讲,则触碰到右边缘,即便是浮动的也是如此,即不会发生margin穿透;
  4. 造成了BFC的区域不会与float box重叠;
  5. 计算BFC高度时,子浮动元素也参与计算(BFC会确切包含浮动的子元素,即闭合浮动);

【补充 2019/04/10】 针对2的内容,有朋友提出了,普通布局流中,同一个父box(不管是不是BFC)的两个相邻的box元素的垂直方向任然也会发生重叠。是的,但若是父box是个BFC,那它存在以下特色: (1) 普通流中,若是父box的直属子box设定了垂直margin,则它并不会撑大父元素,效果以下:

上图中,设定两个子元素p为margin:20px 0,能够看到p之间有重叠,但它们和父box元素的间距是0;

(2)针对上述问题,若是把父box设为BFC(给一个overflow:hidden),则效果以下:

这下父box就被撑开啦,但此时子box之间的垂直方向的margin仍然是重叠的。

因此,再遇到下面这些问题时,就能够回答了:

  1. 如何保证一个div元素不被同级的浮动元素覆盖:设置该div元素为BFC;
  2. 为何父div设置overflow:hidden就能够在其子div为浮动的状况下依然能够撑开:由于此时父div是个BFC。

可是!这里我还想说一下个人一些想法,即:我认为,之因此提出BFC的概念,其主要目的是为了隔离出独立容器,而容器自己与其余元素之间是否彻底知足上述特性,这应该区别对待,咱们应该把BFC的核心思惟用在它自己内部而非外部,后面文章会有例子。

3. 触发BFC的条件

有朋友罗列了好多,记住一些常规的便可:

  1. 根元素或包含根元素的元素,这里应该就是body元素
  2. 浮动元素(float不是none);
  3. 绝对定位元素(position:absolute/fixed);
  4. 行内块元素(display:inline-block);
  5. 表格单元格(display:table-cell ,html表格单元格默认为该值);
  6. 表格标题(display:table-caption , html表格标题默认为该值);
  7. 匿名表格单元格元素(display:table / table-row / table-row-group / table-header-group / table-footer-group / inline-table ,分别是html table 、row、tbody、thead、tfoot的默认属性);
  8. overflow:非visible块元素;
  9. display:flow-root;
  10. contain:layout / content / strict;
  11. 弹性元素(display:flex / inline-flex 元素的直接子元素);
  12. 网格元素(display:grid / inline-grid 元素的直接子元素);
  13. 多列容器(元素的column-count 或 column-width 不为 auto,且包括 column-count为1);
  14. column-span 为all 的元素始终会建立一个新的BFC,即便该元素没有报过在一个多列容器中;

因此,每次看到 overflow:hidden、float:left/right 、position:absolute/fixed ,不用怀疑,必定是BFC

4. 实际使用场景

BFC在实际开发布局中基本能够作这两件事:

  1. 避免因为子元素浮动形成父元素塌陷;
  2. 避免同一个BFC中的两个块级元素的垂直方向margin重叠(设置其中一个为一个新的BFC,永久隔绝外部影响);
  3. 自适应两栏布局。

5. BFC实例

直接看看吧

<body>
    <div class='box'>
	   <div class='left'>左边</div>
	   <div class='right'>右边
		 <div class='little'>1</div>
		 <div class='little'>2</div>
		 <div class='little'>3</div>
	   </div>
	</div>
</body>
<style>
.box {
  background:#888;
  overflow:hidden;
  margin-left:50px;
}
.left {
  background: #73DE80; /* 绿色 */
  width:200px;
  height:200px;
}
.right {
  background: #EF5BE2; /* 粉色 */
  width:400px;
  min-height:100px;
}
.little {
    background: #fff;
	width: 50px;
	height: 50px;
	margin: 10px;
	float:left;
}
</style>
复制代码

效果以下:

image

若是忽然把div left元素 添加一个float:left:

image

看到了吧!div right元素的子元素腾地方了,那接下来把div right变成一个BFC,好比使用:overflow:hidden,效果以下:

image

这样,就知足了BFC内部元素不受外界干扰,且不会与float元素重叠两个特性。

可是,若是我给box right 元素设置了绝对定位,那它是会覆盖box left这个浮动元素的,可这就不符合BFC的不会与float元素重叠这个特性了

image

因此我提出了我和我同事讨论出的想法,即咱们不能把上述罗列的BFC特性完全确定,由于这里涉及到的是两个大的知识层。当设置了绝对定位,虽然也触发了BFC,可是它更是直接影响了层级关系,因此优先实现后者。

以上就是我想提醒广大和我同样的初级朋友,欢迎你们批评指正,谢谢您!!!~~~

参考文献
  1. 《学习 BFC》 juejin.im/post/59b73d…
  2. 《关于BFC理解》 reng99.cc/2018/08/12/…
相关文章
相关标签/搜索