CSS3与页面布局学习总结(三)——BFC、定位、浮动、垂直居中
CSS3与页面布局学习总结(三)——BFC、定位、浮动、垂直居中
一、BFC与IFC
1.1、BFC与IFC概要
BFC(Block Formatting Context)即“块级格式化上下文”, IFC(Inline Formatting Context)即行内格式化上下文。常规流(也称标准流、普通流)是一个文档在被显示时最常见的布局形态。一个框在常规流中必须属于一个格式化上下文,你可以把BFC想象成一个大箱子,箱子外边的元素将不与箱子内的元素产生作用。
BFC是W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。也可以说BFC就是一个作用范围。
在普通流中的 Box(框) 属于一种 formatting context(格式化上下文) ,类型可以是 block ,或者是 inline ,但不能同时属于这两者。并且, Block boxes(块框) 在 block formatting context(块格式化上下文) 里格式化, Inline boxes(块内框) 则在 Inline Formatting Context(行内格式化上下文) 里格式化。
1.2、如何产生BFC
当一个HTML元素满足下面条件的任何一点,都可以产生Block Formatting Context:
a)、float的值不为none
b)、overflow的值不为visible
c)、display的值为table-cell, table-caption, inline-block中的任何一个
d)、position的值不为relative和static
CSS3触发BFC方式则可以简单描述为:在元素定位非static,relative的情况下触发,float也是一种定位方式。
1.3、BFC的作用与特点
a)、不和浮动元素重叠,清除外部浮动,阻止浮动元素覆盖
如果一个浮动元素后面跟着一个非浮动的元素,那么就会产生一个重叠的现象。常规流(也称标准流、普通流)是一个文档在被显示时最常见的布局形态,当float不为none时,position为absolute、fixed时元素将脱离标准流。
没有BFC的情况:
示例代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
运行结果:
此时的div1因为float已经产生了BFC,在div2中添加样式overflow:hidden让其产生BFC,代码如下:
#div2{ width: 300px; height: 300px; background: lightblue; overflow: hidden; }
运行结果:
b)、清除元素内部浮动,计算浮动元素的高度
只要把父元素设为BFC就可以清理子元素的浮动了,最常见的用法就是在父元素上设置overflow: hidden样式,对于IE6加上zoom:1就可以了(IE Haslayout)。
当一个元素的内部元素浮动时不会计算其高度,示例如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
运行结果:
修改div0让其触发BFC,还原高度,代码如下:
#div0 { border: 2px solid lightsalmon; padding: 20px; width: 400px; overflow: hidden; /*让div0触发BFC*/ }
运行结果:
c)、外边距将不再与上下文之外的元素折叠
示例代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
如果此时将脚本的div1与div2同时变成BFC环境,修改的css如下:
#div1 { width: 200px; height: 200px; background: lightgreen; margin-bottom: 100px; overflow: hidden; } #div2 { width: 200px; height: 200px; background: lightblue; margin-top: 100px; overflow: hidden; }
执行时会发现效果还是一样,此时的div1与div2都是BFC上下文,但是要求的是:外边距将不再与上下文之外的元素折叠,按照要求,我们应该将div1与div2放在不同的上下文中,修改后的脚本如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>BFC与IFC</title> <style type="text/css"> #div1 { width: 200px; height: 200px; background: lightgreen; margin-bottom: 100px; } #div2 { width: 200px; height: 200px; background: lightblue; margin-top: 100px; } #div2-outer { overflow: hidden; } </style> </head> <body> <h2>BFC与IFC</h2> <div id="div1">div1 </div> <div id="div2-outer"> <div id="div2">div2 </div> </div> </body> </html>
运行结果如下:
d)、元素会一个接一个地被垂直放置,它们的起点是一个包含块的顶部(文字不会环绕布局)
示例代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
没有BFC时的运行结果:
从运行结果可以看出div与p还是重叠了,只是文字被挤出,和前面提到的重叠是同一个意思,将p元素触发BFC后的效果如下图所示:
p{ overflow: hidden; }
运行结果:
1.4、IE与Layout
Layout是 IE 浏览器渲染引擎的一个组成部分。在 IE 浏览器中,一个元素要么自己对自身的内容进行组织和计算大小, 要么依赖于包含块来计算尺寸和组织内容,hasLayout 与 BFC 有很多相似之处。在IE中,元素使用“布局”概念来控制尺寸和定位,分为拥有布局和没有布局两种情况,拥有布局的元素由它控制本身及其子元素的尺寸和定位,而没有布局的元素则通过父元素(最近的拥有布局的祖先元素)来控制尺寸和定位,而一个元素是否拥有布局则由 hasLayout 属性告知浏览器,它是个布尔型变量,true 代表元素拥有布局,false 代表元素没有布局。简而言之,hasLayout 只是一个 IE 下专有的属性,hasLayout 为 true 的元素浏览器会赋予它一系列的效果。
特别注意的是,hasLayout 在 IE 8 及之后的 IE 版本中已经被抛弃,所以在实际开发中只需针对 IE 8 以下的浏览器为某些元素触发 hasLayout。
出发IE下的haslayout方法:
display: inline-block
height: (除 auto 外任何值)
width: (除 auto 外任何值)
float: (left 或 right)
position: absolute
writing-mode: tb-rl
zoom: (除 normal 外任意值)
min-height: (任意值)
min-width: (任意值)
max-height: (除 none 外任意值)
max-width: (除 none 外任意值)
overflow: (除 visible 外任意值,仅用于块级元素)
overflow-x: (除 visible 外任意值,仅用于块级元素)
overflow-y: (除 visible 外任意值,仅用于块级元素)
position: fixed
综合前面的内容清除浮动的写法如下:
.floatfix{
*zoom:1; /*在旧版本的IE浏览器缩放大小,触发haslayout*/
}
.floatfix:after{
content:"";
display:table;
clear:both;
}
1.5、IFC
除了BFC还有IFC,GFC,FFC,是不同格式化上下文(Formatting Context)的简称,GFC是网格格式化上下文(Grid Formatting Context),FFC是弹性盒格式化上下文(Flex Formatting Context),FKC是开封菜的意思:)。
二、定位
使用css布局position非常重要,他的语法如下:
position:static | relative | absolute | fixed | center | page | sticky
默认值:static,center、page、sticky是CSS3中新增加的值。
2.1、static
可以认为静态的,默认元素都是静态的定位,对象遵循常规流。此时4个定位偏移属性不会被应用,也就是使用left,right,bottom,top将不会生效。
示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
运行结果:
定义偏移并未起作用。
2.2、relative
相对定位,对象遵循常规流,并且参照自身在常规流中的位置通过top,right,bottom,left这4个定位偏移属性进行偏移时不会影响常规流中的任何元素。
示例代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>相对定位</title> <style type="text/css"> div { width: 200px; height: 200px; background: lightblue; margin: 10px; } #div1 { position: relative; /*相对定位*/ left:30px; /*在自己原有位置上相对左边偏移30像素*/ bottom: -30px; background: lightgreen; } </style> </head> <body> <div id="div1">div1 </div> <div id="div2">div2 </div> </body> </html>
运行结果:
2.3、absolute
绝对定位,对象脱离常规流,此时偏移属性参照的是离自身最近的定位祖先元素,如果没有定位的祖先元素,则一直回溯到body元素。盒子的偏移位置不影响常规流中的任何元素,其margin不与其他任何margin折叠。
元素定位参考的是离自身最近的定位祖先元素,要满足两个条件,第一个是自己的祖先元素,可以是父元素也可以是父元素的父元素,一直找,如果没有则选择body为对照对象。第二个条件是要求祖先元素必须定位,通俗说就是position的属性值为非static都行。
示例代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>绝对定位</title> <style type="text/css"> div { border: 2px solid darkturquoise; padding: 10px; } #div1 { width: 400px; height: 400px; } #div2 { width: 300px; height: 300px; } #div3 { width: 200px; height: 200px; position: absolute; right: 5px; top: 5px; } </style> </head> <body> <div id="div1"> div1 <div id="div2"> div2 <div id="div3">div3 </div> </div> </div> </body> </html>
运行结果:
因为div3使用absolute绝对定位,它的参考对象是父元素div2,div1都不满足条件,因为两者都没有进行定位,是默认的定位值static,根据约定最终找到body,所以会出现在页面的右上角。此时如果想让div3的参照对象为div1,则可以修改代码为:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>绝对定位</title> <style type="text/css"> div { border: 2px solid darkturquoise; padding: 10px; } #div1 { width: 400px; height: 400px; position: relative; /*相对定位*/ } #div2 { width: 300px; height: 300px; } #div3 { width: 200px; height: 200px; position: absolute; right: 5px; bottom: 5px; } </style> </head> <body> <div id="div1"> div1 <div id="div2"> div2 <div id="div3">div3 </div> </div> </div> </body> </html>
运行结果:
2.4、fixed
固定定位,与absolute一致,但偏移定位是以窗口为参考。当出现滚动条时,对象不会随着滚动。
如下图所示:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>固定定位</title> <style type="text/css"> body{ height: 3000px; } #top{ width: 50px; height: 70px; line-height: 70px; text-align: center; background: lightblue; position: fixed; right: 1px; bottom: 30%; } </style> </head> <body> <h2 id="title">固定定位</h2> <div id="top"><a href="#title">回顶部</a></div> </body> </html>
运行结果:
center:
与absolute一致,但偏移定位是以定位祖先元素的中心点为参考。盒子在其包含容器垂直水平居中。(CSS3)
page:
与absolute一致。元素在分页媒体或者区域块内,元素的包含块始终是初始包含块,否则取决于每个absolute模式。(CSS3)
sticky:
对象在常态时遵循常规流。它就像是relative和fixed的合体,当在屏幕中时按常规流排版,当卷动到屏幕外时则表现如fixed。该属性的表现是现实中你见到的吸附效果。(CSS3)
2.5、菜单
使用前面的内容实现了一个简单的下拉菜单,效果如下:
菜单结构:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)