前端基础|从BFC到清除浮动

312 阅读7分钟

BFC全称是Block Formatting Context,即块格式化上下文。它是CSS2.1规范定义的,关于CSS渲染定位的一个概念。要明白BFC到底是什么,首先来看看什么是视觉格式化模型,以及CSS中的三种定位方案。

视觉格式化模型

视觉格式化模型定义了盒(Box)的生成。盒主要包括了块盒、行内盒、匿名盒(没有名字不能被选择器选中的盒)以及一些实验性的盒(未来可能添加到规范中)。盒的类型由display属性决定。

块盒(block box)

display:block; display:list-block; display:table;

  • 常见块级元素:p/ul/ol/li/h1~h6/div/form/table
  • 独占一行
  • 可以设置宽高大小,以及内外边距,默认宽度为本身父容器的100%

行内盒(inline box)

display:inline; display:inline-block; display:inline-table;

  • 常见行内元素:i/b/span/a/button/input
  • 不会自动进行换行
  • 元素的宽高不可设置
  • 内边距可以设置;外边距水平方向有效,竖直方向无效
  • 元素宽度在不设置的情况下,随内部元素的内容变化

匿名盒(anonymous box)

匿名盒也有份匿名块盒与匿名行内盒,因为匿名盒没有名字,不能利用选择器来选择它们,所以它们的所有属性都为inherit或初始默认值。

三个定位方案

一.常规流(Normal flow)

  • 除根元素、浮动元素和绝对定位元素外,其他元素都在常规流之内(in-flow)
  • 根元素、浮动元素和绝对元素会脱离常规流(out of flow)
  • 对于静态定位(static positioning),position: static,盒的位置是常规流布局里的位置。此时top,right,bottom,leftz-index属性无效。
  • 对于相对定位(relative positioning),position: relative,盒偏移位置由这些属性定义:topbottomleftright。即使有偏移,仍然保留原有的位置,其它常规流不能占用这个位置(因此会在此元素未添加定位时所在位置留下空白)

二.浮动(Floats)

定义

  • 浮动元素从常规流/文档流中脱离,按照指定浮动方向发生移动,漂浮在容器(包含块)的左边或右边
  • 浮动盒会一直漂浮到其外边缘挨到父级容器边缘或另外相邻的浮动盒(常规流环绕在它的周边)
.father {
width: 300px;
margin: 0 auto;
border: 5px solid #444;
}
.son {
width: 200px;
height: 200px;
background: rgb(238, 197, 14);
float: left;
}
<div class="father">
  我是父级元素
  <div class="son">我是子元素</div>
  <p><span>这是父级元素里面的内容</span></p>
</div>

影响

  • 高度塌陷 在文档流中,父元素的高度默认是被子元素撑开的,即子元素多高,父元素就多高。但当子元素设置浮动之后,子元素会完全脱离文档流,此时将会导致子元素无法撑起父元素的高度,表现为父元素的高度塌陷。
  • 字围现象 浮动元素不会挡住没有浮动元素中的文字,没有浮动的文字会自动给浮动的元素让位置,这个就是浮动元素字围现象(浮动元素不会影响其后面的流内块级盒,但是浮动元素后面的行级盒子会变短以避开浮动元素)。不仅如此,浮动元素甚至会影响到页面中其他位于其下的元素的排版。

三.绝对定位(Absolute positioning)

  • 盒从常规流中被移除,不影响常规流的布局
  • 对于position: absolute,元素定位将相对于最近的一个relativefixedabsolute的父元素(非 static定位的祖先元素),如果没有则相对于body

块格式化上下文(Block Formatting Context)

到这里,已经对CSS的定位有一定的了解了,从上面的信息中也可以得知,BFC是页面CSS视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域

这个规则规定了: 1.页面必须自动包含突出的浮动元素 2.所有块级盒子的左边界默认与包含块的左边界对齐

实现BFC的方式

  • 根元素(<html>)
  • display属性值设置为inline-blocktable-cell等的元素,可以为内容创建类似块级的上下文
  • float属性值不是none的元素
  • 绝对定位的元素(position的值为absolutefixed
  • overflow属性值不是visible的元素
  • displayflexinline-flex的元素

(其中,最常见的是overflow:hiddenfloat:left/rightposition:absolute。也就是说,每次看到这些属性的时候,就代表了该元素以及创建了一个BFC了)

BFC的特性

  • 内部的盒会在垂直方向一个接一个排列(可以看作BFC中有一个的常规流)
  • box垂直方向的距离由margin决定
  • 属于同一个BFC的两个相邻box的margin会发生重叠
  • 每个元素的margin box的左边,与容器块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此
  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然**(最显著的特性)**
  • BFC的区域不会与float box重叠
  • 计算BFC的高度时,考虑BFC所包含的所有元素,连浮动元素也参与计算

BFC的作用

  • 自适应双栏布局
  • 分属于不同的BFC时可以阻止margin重叠
  • 清除内部浮动(可以包含浮动元素)

当一个元素具备了触发新块级格式化上下文的条件,并且挨着一个浮动元素时,它就会忽略自己的边界必须接触自己的包含块边界的规则。此时,这个元素会收缩到适当大小,不仅行盒子如此,所有盒子都如此。


清除CSS浮动

在前文介绍块格式化上下文的时候,我们已经了解到浮动这一现象及其影响。下面介绍清除浮动的几种方法。

一.给父级元素定义高度height

原理:高度塌陷是因为浮动元素的父元素的高度自适应导致的,那么我们给它设置适当的高度就可以解决这个问题了

缺点:只适合高度固定的布局,需要给出精确的高度,如果父级元素高度不合适,还是会产生溢出问题

二.为父元素创建BFC

  • 给父级元素也添加浮动float

原理:通过浮动框创建BFC,利用其特性(每个元素的margin box的左边,与容器块border box的左边相接触,即使存在浮动也是如此)清除浮动

缺点:与父元素相邻的元素布局会受到影响,另外需要给每个浮动元素父级添加浮动,浮动多了容易出现问题

  • 给父级元素设置display: inline-block属性

原理:通过非块级的容器inline-block创建BFC,利用其特性(同上)清除浮动

缺点:父级的margin左右auto失效,无法使用margin: 0 auto;设置居中

  • 给父级元素添加overflow: hidden/auto属性

原理:通过overflow: hidden/auto属性创建BFC,利用其特性(同上)清除浮动

缺点:不能和position配合使用,因为超出的内容会被修剪

三.在浮动元素下面添加空的div,为其加clear类

原理:利用clear: both;清除浮动,让父级元素能自动获取到高度

.clear{height: 0; font-size: 0; clear: both;}

缺点:会添加大量无语义标签,结构与表现未分离,不利于维护

四.利用:after伪类(推荐用法)

原理:原理同上,但IE8以上和非IE浏览器才支持:after。为了兼容IE,需要使用zoom:1(设置或检索对象的缩放比例,Firefox不支持)触发hasLayout( 根据元素自身内容进行计算大小和组织,或者依赖于父元素来计算尺寸和组织内容)

.clear{zoom:1;} /*兼容ie6*/
.clear:after{
    content:"";
    display:block;
    clear:both;
}