CSS中的定位方案以及float详解

序言

CSS2.1规范中关于定位方案分为三种:

  • 正常排版Normal flow:
    框在正常排版中必然属于一个格式上下文。要么是 块格式化上下文(Block formatting contexts:BFC),要么是 行格式化上下文(Inline formatting contexts:IFC)。也有一些人把正常排版称之为文档流或者是普通流。
  • 浮动 Floats:
    在浮动模型中,一个框先按照正常排版来摆放,再将它从排版流中取出并尽可能地向左或向右偏移。其它内容可以排在一个浮动的周围。简而言之,在当前行向左或向右偏移的框就是浮动框。浮动框最有趣的特点是其它内容可以紧挨着它的一侧来排版(也可以通过clear属性来禁止这样排版)。内容会紧挨着左浮动框的右侧排版,而紧挨着右浮动框的左侧排版。
  • 决对定位 Absolute positioning:
    绝对定位模型中,一个框基于它的包含块而显式地偏移。它完全从正常排版中脱离(它对后面的元素不会有影响)。一个绝对定位框为它的正常排版子元素和绝对地定位(不是fixed)后代生成一个新的包含块。不过,绝对定位元素的内容不会在其它框的周围排列。它们可能会也可能不会挡住另外一个框的内容(或者被挡住),这取决于互相重合的框的堆叠层次。

正常排版 Normal flow

块格式化上下文 (BFC)

在规范中的介绍是:有这几种框会为其内容创建新的块格式化上下文:浮动框、绝对定位框、非块框的块容器、overflow属性非visible的块框。

其实说的就是以下这几种情况能够创建一个新的BFC:

  • 浮动元素,即float属性不为none的元素。
  • 绝对定位元素,即position属性为absolute或者是fixed的元素。
  • 非块框的块容器指的是:行内块 inline-blocks(display属性设置为 inline-block)、表格单元格(display属性设置为:table-cell)、表格标题(display属性设置为table-caption)。
  • overflow不为visible的元素,即overflowautohidden等。
  • 根元素或其它包含它的元素。
  • 弹性盒模型(元素的 display: flexinline-flex)。

在块格式化上下文中,框会从包含块的顶部开始,一个接一个地,垂直向下地摆放。两个兄弟框之间的垂直距离由 margin 属性来决定。

在同一个块格式化上下文中,相邻的块级框之间的垂直外边距会出现折叠。相关折叠外边距的内容可以参考W3C规范: 折叠外边距

BFC一个很重要的特性就是:计算BFC的高度时,考虑BFC所包含的所有元素,连浮动元素也参与计算,通过这个特性我们就可以来实现 闭合浮动了。

行格式化上下文(IFC)

  • 在行格式化上下文中,框会从包含块的顶部开始,一个接一个地水平摆放。
  • 水平方向上IFC的外边距、边框、内边距所占用的空间都会被考虑在内。
  • 垂直方向上,IFC可能会以不同形式来对齐:它们可能会把底部或顶部对齐,也可能把其内部的文本基线对齐。
  • 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的 行框。行框的宽度是由包含块和存在的浮动来决定,行框的高度由行高计算规则来决定。
  • 行框一定会高到足以容纳它所包含的全部框。然而,它也可能比它所包含的最高的框还要高(例如:这些框是以基线对齐)。当一个行内框的高度小于行框的高度时,可以使用vertical-align来确定这个行内框的垂直位置。

相对定位(Relative positioning)

当一个框按照正常排版或浮动来摆放好之后,它就可能相对当时的位置再有所偏移,这被称作 相对定位

一个框进行相对定位偏移了,它后面元素的位置不会发生任何改变,然后有可能导致相互重叠。

对于相对定位元素,leftright属性会在不改变其框尺寸的情况下水平地移动框。

有以下几种使用left和right进行相对定位的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<style>
div{
width:100px;
margin:30px;
height:100px;
background:#c33;
color:#fff;
text-align:center;
line-height:100px;
border:5px solid #ccc;
opacity:1;
}
div:nth-child(2){
position:relative;
left:auto;
right:30px;
background:#658;
}
div:nth-child(3){
position:relative;
left:auto;
right:auto;
background:#aa6;
}
div:nth-child(4){
position:relative;
left:30px;
right:auto;
background:#69c;
}
</style>
<div id="a">AAA</div>
<div id="b">BBB</div>
<div id="c">CCC</div>
<div id="d">DDD</div>

relative position

浮动 Floats

一个浮动框会向左或向右进行偏移直到其外边缘紧贴其包含块的边缘或另一个浮动框的外边缘。如果摆放浮动框时,当前行已有一个行框,则浮动框的顶部外边缘会与该行框的顶部对齐。

由于浮动框不属于正常排版(正常文档流),所以浮动框前后的非定位框就会当浮动框不存在一样按照原来的排版顺序进行排版,但是浮动框当前行的行框的宽度会根据浮动框进行改变,如果宽度太小不足以容纳下行框,那么行框就会继续向下移,直到没有浮动框为止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<style>
#b{
width:100px;
margin:30px;
padding:30px;
background:#c33;
color:#fff;
text-align:center;
line-height:100px;
border:5px solid #ccc;
background:#658;
}
[class^=b]{
float:left;
width:40px;
height:40px;
margin:10px;
background:#fff;
}
</style>
<div id="b">
<div class="b-a"></div>
<div class="b-b"></div>
<div class="b-c"></div>
</div>

flaot

从上面这个Demo中看到,在b这个框内部的浮动框超出了b的范围,或者说是b没有根据内部的内容高度来扩展自己的高度。

清除浮动 & 闭合浮动

  • 清除浮动:“清除浮动”源于clear float即W3C CSS2.1 9.5.2章定义的内容,意即使用clear阻止这个元素盒子的边和前面的浮动元素相邻的行为;
  • 闭合浮动:避免“float无法撑高父容器的默认行为”,减少浮动带来的影响。
闭合浮动

我们目前要解决的就是闭合浮动,有如下两类方法:

  • 通过在浮动元素的末尾添加一个空元素,设置 clear:both属性。
  • 上面说过了,一个BFC元素会连浮动元素也参与计算高度,所以可以通过一些设置让父元素变为一个BFC。
添加空元素
  • 添加额外的标签,如div,设置一下css属性。
1
<div  style="clear:both"></div>

但是通过这种方法会添加一些没有什么含义的标签,不符合web语义化,有违结构与表现的分离。

  • 使用 br标签和其自身的 html属性:br 有 clear=“all | left | right | none” 属性。
1
<br  clear="both"/>

此方法同样有违结构与表现的分离,不推荐使用。

修改父元素使他变成一个BFC
  • 父元素设置 overflowhidden或者auto,在IE6中还需要触发 hasLayout ,例如 zoom:1;
1
2
3
4
#b{
overflow:hidden;
*zoom:1;
}

使用hidden的时候如果内容增多,父元素不会自动变高,造成内容被隐藏。

使用auto的时候,如果多个嵌套后,firefox某些情况会造成内容全选;IE中 mouseover 造成宽度改变时会出现最外层模块有滚动条等,firefox早期版本会无故产生focus等。

  • 父元素也设置浮动,这个方法虽然代码量特别少并且不需要添加标签,但是这个方法会使得父元素的布局发生变化,而且不可能一直浮动到body元素。
  • 父元素设置display属性,比如说设置为table等值,但是这个方法会改变盒子模型属性,并且会因此造成一些其它的问题,不推荐使用。
  • 使用伪元素,也就是网上好多网友说的使用.clearfix。
1
2
3
4
5
6
7
8
9
10
.clearfix:before,.clearfix:after{
content="";
display: table;
}
.clearfix:after {
clear: both;
}
.clearfix{
zoom:1;
}

此方法应该是目前来说最好的实践了。

下面是上面那个代码为父元素添加闭合浮动后的代码与效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<style>
body{
background:#333;
}
#b{
width:100px;
margin:30px;
padding:30px;
background:#c33;
color:#fff;
text-align:center;
line-height:100px;
border:5px solid #ccc;
background:#658;
overflow:hidden;
}
[class^=b]{
float:left;
width:40px;
height:40px;
margin:10px;
background:#fff;
}
</style>
<div id="b">
<div class="b-a"></div>
<div class="b-b"></div>
<div class="b-c"></div>
</div>

close float

绝对定位 Absolute positioning)

绝对定位模型一般来说是指由position设置为absolutefixed来创建的。它会从正常排版(正常文档流)中脱离出来,对后面的元素没有影响,并且会为子元素创建一个新的包含块。

绝对定位元素可能会遮挡住其它的内容,也可能不会遮挡,这取决于绝对定位元素的堆叠层次(z-index)。

fixedabsolute的区别在于fixed定位不是基于【第一个position不是static的父元素 或者body元素】来定位的,而是根据 整个视图窗口来定位的,也就是指我们所看到的浏览器窗口,因此当页面滚动条滑动的时候,由于相对于浏览器窗口的位置没有变化,所以fixed元素的位置就不会变化。

“display”、”position” 与 “float” 的关系:

  • 如果display值为none,那么positionfloat无效,元素不生成框。
  • 否则,如果position值为absolute或者fixed,那么框绝对地定位float计算的值为none,并且 display根据下面的表格进行设定。框的位置由top, right, bottomleft属性和包含块决定。
  • 否则,如果float的值不是none,该框是浮动的,且display`值根据下面的表格进行设定。
  • 否则,如果元素是根元素,display值根据下面的表格进行设定。
  • 否则,display 的计算值为指定的值。

display

小结

首先说明一下下哈,,这篇文章是我看的我朋友的一篇博客,原文请点击 这里。然后我看了相关的规范,感觉忽然明白了好多东西,,不过里面的名词有点多,,有很多我还是没有搞很明白,,还在进一步的学习之中,,希望大家也深入学习一下~~ 加油奥~~