为什么要把这个知识点单独拿出来记录,是因为这个是css最基础、最重要,也是一个难点、面试如果只要问到了css相关的,这个知识点应该是必问的,所有有必要单独拿出来说。
1.概念
css盒模型:可以认为每个html标签都是一个方块,然后这个方块又包着几个小方块,如同盒子一层层的包裹着,这就是所谓的盒模型,
盒模型分为IE盒模型和W3C标准盒模型
2.IE盒模型和W3C标准盒模型的区别是什么
W3C标准盒模型:属性width,height只包含内容content,不包含border和padding。
IE盒模型:属性width,height包含border和padding,指的是content+padding+border
在ie8+浏览器中使用哪个盒模型可以由box-sizing(CSS新增的属性)控制,默认值为content-box,即标准盒模型;如果将box-sizing设为border-box则用的是IE盒模型。如果在ie6,7,8中DOCTYPE缺失会触发IE模式。在当前W3C标准中盒模型是可以通过box-sizing自由的进行切换的。
content-box(标准盒模型)
width = 内容的宽度
height = 内容的高度
border-box(IE盒模型)
width = border + padding + 内容的宽度
height = border + padding + 内容的高度
谷歌浏览器,按下F12,然后把右边栏的滚动条拉到最下面你就会看到一个东西:
通过代码就能更直观的理解
.box{ width:200px; height:200px;}// 此时,盒子大小就是content的大小
还是这个盒子,如果加上padding
.box{ width:200px; height:200px; padding:20px;}// 此时,盒子的长宽变成了240x240
显然,padding是能够改变盒子的大小的,这时盒子大小就等于content+padding
那如果加上border呢
.box{ width:200px; height:200px; padding:20px; border:10px solid black;}// 此时,盒子的长宽变成了260x260
所以这时盒子大小就等于content+padding+border
继续加上margin
.box{ width:200px; height:200px; background-color:pink; padding:20px; border:10px solid black; margin-bottom:10px;}.box1{ width: 100px; height: 100px; background: green;}// 此时,盒子的长宽仍为260x260,即盒子的大小并未发生变化,盒子的底部产生了10px的空白
所以说,盒子的大小为content+padding+border即内容的(width)+内边距的再加上边框,而不加上margin。很多时候,我们会错误地把margin算入,若那样的话,上面这种情形盒子的大小应该是260x270,但实际情况并不是这样的。
css的盒模型由content(内容)、padding(内边距)、border(边框)、margin(外边距)组成。但盒子的大小由content+padding+border这几部分决定,把margin算进去的那是盒子占据的位置,而不是盒子的大小!
3.box-sizing对盒模型的影响
我们可以试着给上面的粉色方块设置box-sizing属性为border-box发现,会发现:无论我们怎么改border和padding盒子大小始终是定义的width和height
.box{ width:200px; height:200px; box-sizing:border-box; padding:20px;}// 此时,盒子的大小始终是200*200
我们在编写页面代码时应尽量使用标准的W3C模型(需在页面中声明DOCTYPE类型),这样可以避免多个浏览器对同一页面的不兼容。因为若不声明DOCTYPE类型,IE浏览器会将盒子模型解释为IE盒子模型,FireFox等会将其解释为W3C盒子模型;若在页面中声明了DOCTYPE类型,所有的浏览器都会把盒模型解释为W3C盒模型。
1.什么是BFC
BFC:块级格式化上下文(Block Fromatting Context),指一个隔离的独立的块级渲染区域,是 Web 页面的可视化 CSS 渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。
注意:一个 BFC 的范围包含创建该上下文的所有子元素,但不包括 创建了新 BFC 的子元素的内部元素。这从另一个角度说明,一个元素不能同时存在于两个 BFC 中。因为如果一个元素能够同时处于两个 BFC 中,那么就意味着这个元素能与两个 BFC 中的元素发生作用,就违反了 BFC 的 隔离作用
2.文档流
我们常说的文档流其实分为 定位流、浮动流 和 普通流 三种。而普通流其实就是指 BFC 中的 FC。FC(Formatting Context),直译过来就是格式上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其他元素之间的关系和作用。常见的 FC 有 BFC、IFC(内联元素格式化上下文)、GFC 和 FFC。
3.常规流
在常规流中,盒子一个接着一个排列;
在块级格式化上下文里面,它们垂直方向排列;
在行内格式化上下文里面,它们水平方向排列;
当 position 为 static 或 relative,并且 float 为 none 时会触发常规流;
对于静态定位(static positioning),position: static,盒的位置是常规流布局里的位置;
对于相对定位(relative positioning),position: relative,盒偏移位置由 top、bottom、left、right 属性定义。即使有偏移,仍然保留原有的位置,其它常规流不能占用这个位置
4.浮动流
左浮动元素尽量靠左、靠上,右浮动同理,这导致常规流环绕在它的周边,除非设置 clear 属性;
浮动元素不会影响块级元素的布局,但浮动元素会影响行内元素的布局,让其围绕在自己周围,撑大父级元素,从而间接影响块级元素布局;
最高点不会超过当前行的最高点、它前面的浮动元素的最高点;
不超过它的包含块,除非元素本身已经比包含块更宽;
行内元素出现在左浮动元素的右边和右浮动元素的左边,左浮动元素的左边和右浮动元素的右边是不会摆放浮动元素的;
5.定位流
绝对定位方案,盒从常规流中被移除,不影响常规流的布局;
它的定位相对于它的包含块,相关 CSS 属性:top、bottom、left、right;
如果元素的属性 position 为 absolute 或 fixed,它是绝对定位元素;
对于 position: absolute,元素定位将相对于上级元素中最近的一个 relative、fixed、absolute,如果没有则相对于 body
7.BFC 触发条件
7.BFC 约束规则
浏览器对 BFC 区域的约束规则:
生成 BFC 元素的子元素会一个接一个的放置;
垂直方向上他们的起点是一个包含块的顶部,两个相邻子元素之间的垂直距离取决于元素的 margin 特性。在 BFC 中相邻的块级元素的外边距会折叠(Mastering margin collapsing)。
生成 BFC 元素的子元素中,每一个子元素左外边距与包含块的左边界相接触(对于从右到左的格式化,右外边距接触右边界),即使浮动元素也是如此(尽管子元素的内容区域会由于浮动而压缩),除非这个子元素也创建了一个新的 BFC(如它自身也是一个浮动元素)。
规则解读:
在 BFC 的垂直方向上,边距会发生重叠(margin collapse)
每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明 BFC 中子元素不会超出他的包含块,而 position 为 absolute 的元素可以超出他的包含块边界)
BFC 的区域不会与 float 的元素浮动区域重叠
计算 BFC 的高度时,浮动子元素也参与计算
8.使用场景
(1)防止margin重叠(塌陷)
<style> p { color: #f55; background: #fcc; width: 200px; line-height: 100px; text-align:center; margin: 100px; }</style><body> <p>Haha</p > <p>Hehe</p ></body>
两个p元素之间的距离为100px,发生了margin重叠(塌陷),以最大的为准,如果第一个P的margin为80的话,两个P之间的距离还是100,以最大的为准。
同一个BFC的俩个相邻的盒子的margin会发生重叠,可以在p外面包裹一层容器,并触发这个容器生成一个BFC,那么两个p就不属于同一个BFC,则不会出现margin重叠
<style> .wrap { overflow: hidden; // 新的BFC } p { color: #f55; background: #fcc; width: 200px; line-height: 100px; text-align:center; margin: 100px; }</style><body> <p>Haha</p > <div class="wrap"> <p>Hehe</p > </div></body> // 这时候,边距则不会重叠
(2)清除内部浮动
<style> .par { border: 5px solid #fcc; width: 300px; } .child { border: 5px solid #f66; width:100px; height: 100px; float: left; }</style><body> <div class="par"> <div class="child"></div> <div class="child"></div> </div></body>
而BFC在计算高度时,浮动元素也会参与,所以我们可以触发.par元素生成BFC,则内部浮动元素计算高度时候也会计算
.par { overflow: hidden;}
(3)自适应多栏布局
<style> body { width: 300px; position: relative; } .aside { width: 100px; height: 150px; float: left; background: #f66; } .main { height: 200px; background: #fcc; }</style><body> <div class="aside"></div> <div class="main"></div></body>
每个元素的左外边距与包含块的左边界相接触,因此,虽然.aslide为浮动元素,但是main的左边依然会与包含块的左边相接触,而BFC的区域不会与浮动盒子重叠所以我们可以通过触发main生成BFC,以此适应两栏布局
.main { overflow: hidden;}
这时候,新的BFC不会与浮动的.aside元素重叠。因此会根据包含块的宽度,和.aside的宽度,自动变窄
BFC实际就是页面一个独立的容器,里面的子元素不影响外面的元素