浮动、定位和 BFC 边距合并

浮动元素的特性

浮动元素的特征:

  1. 浮动元素会脱离正常的文档流,按照其外边距指定的位置相对于它的上一个块级元素(或父元素)显示。
  2. 浮动元素后面的块级元素的内容会向此浮动元素的外边距靠齐,但是边框和背景却忽略浮动元素而向上一个(实例中为父元素)任意非浮动元素靠齐。
  3. 浮动元素后面的内联元素会向此浮动元素的外边距靠齐。

浮动元素的影响:

  1. 对于其父元素:
  • 它会脱离当前文档流,所以它无法撑开父元素,从而造成父元素的塌陷。
  1. 对其他浮动元素:
  • 同一个方向的浮动元素:当一个浮动元素在浮动过程中碰到同一个方向的浮动元素时,它会紧跟在它们后面。
  • 反方向的浮动元素:互不影响,位于同一条水平线上,当空间不够时会被挤下。
  1. 对普通元素:
  • 该元素会忽视浮动元素的而占据它的位置,并且元素会处在浮动元素的下层(并且无法通过 z-index 属性改变他们的层叠位置)。
  1. 对文字:
  • 文字会环绕在浮动元素周围。

清除浮动

当容器的高度为 auto,且容器的内容中有浮动(float 为 left 或 right)的元素,在这种情况下,容器的高度不能自动伸长以适应内容的高度,使得内容溢出到容器外面而影响(甚至破坏)布局的现象。这个现象叫浮动溢出,为了防止这个现象的出现而进行的处理,就叫清除浮动。
方法:

  1. 使用带 clear 属性的空元素
    在浮动元素后使用一个空元素如 <div class="clear"></div>,并在 CSS 中赋予 .clear { clear:both;} 属性即可清理浮动。亦可使用 <br class="clear" /><hr class="clear" /> 来进行清理。
  2. 使用CSS的overflow属性
    给浮动元素的容器添加 overflow:hidden;overflow:auto; 可以清除浮动,另外在 IE6 中还需要触发 hasLayout ,例如为父元素设置容器宽高或设置 zoom:1
    在添加 overflow 属性后,浮动元素又回到了容器层,把容器高度撑起,达到了清理浮动的效果。
  3. 给浮动的元素的容器也添加浮动
    给浮动元素的容器也添加上浮动属性即可清除内部浮动,但是这样会使其整体浮动,影响布局,不推荐使用。
  4. 使用 CSS 的 :after 伪元素
    给浮动元素的容器添加一个如下的 class,然后给这个 class 添加一个 :after 伪元素实现元素末尾添加一个看不见的块元素(Block element)清理浮动。
clearfix {
    content: "";
    display: block;
    clear: both;
}

结合 :after 伪元素(注意这不是伪类,而是伪元素,代表一个元素之后最近的元素)和触发 hasLayout,可以完美兼容当前主流的各大浏览器。

  1. 使父容器形成 BFC(Block Format Content)来达到清除浮动的效果。

定位方式

常用定位方式有三种:

  1. relative 生成相对定位的元素,相对于元素本身正常位置进行定位,元素的位置通过 left, top, right 以及 bottom 属性进行规定。一般作为绝对定位的元素参考点,或者页面图片的小偏移。
  2. absolute 生成绝对定位的元素,相对于 static 定位以外的第一个祖先元素(offset parent)进行定位,元素的位置通过 left, top, right 以及 bottom 属性进行规定。一般用于元素的水平垂直居中等特定位置。
  3. fixed 生成固定定位的元素,相对于浏览器窗口进行定位。元素的位置通过 left, top, right 以及 bottom 属性进行规定。一般用于固定导航栏,或侧边栏。

z-index

z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。

z-index

层级关系的比较

  1. 对于同级元素,默认( position:static )情况下文档流后面的元素会覆盖前面的。
  2. 对于同级元素,position 不为 static 且 z-index 存在的情况下 z-index 大的元素会覆盖 z-index 小的元素,即 z-index 越大优先级越高。
  3. IE6/7 下 position不为 static,且 z-index 不存在时 z-index 为0,除此之外的浏览器 z-index 为 auto。
  4. z-index 为 auto 的元素不参与层级关系的比较,由向上遍历至此且 z-index 不为 auto 的元素来参与比较。

顺序规则
如果不对节点设定 position 属性,位于文档流后面的节点会遮盖前面的节点。

<div id="a">A</div>
<div id="b">B</div>


定位规则
如果将 position 设为 static,位于文档流后面的节点依然会遮盖前面的节点浮动,,所以 position:static 不会影响节点的遮盖关系。

<div id="a" style="position:static;">A</div>
<div id="b">B</div>

如果将 position 设为 relative (相对定位),absolute (绝对定位) 或者 fixed (固定定位),这样的节点会覆盖没有设置 position 属性或者属性值为 static 的节点,说明前者比后者的默认层级高。

<div id="a" style="position:relative;">A</div>
<div id="b">B</div>

在没有 z-index 属性干扰的情况下,根据这顺序规则和定位规则,可以做出更加复杂的结构。这里我们对 A 和 B 都不设定 position,但对 A 的子节点 A-1 设定 position:relative 根据顺序规则,B 会覆盖 A,又根据定位规则 A-1 会覆盖 B。

<div id="a"> 
  <div id="a-1" style="position:relative;">A-1</div>
</div>
<div id="b">B</div>


参与规则
尝试不用 position 属性,但为节点加上 z-index 属性,发现 z-index 对节点没起作用。z-index 属性仅在节点的 position 属性为 relative,absolute 或者 fixed 时生效。

<div id="a" style="z-index:2;">A</div>
<div id="b" style="z-index:1;">B</div>
<div id="c" style="z-index:0;">C</div>
<div id="a" style="z-index:2;">A</div>
<div id="b" style="position:relative;z-index:1;">B</div>
<div id="c" style="position:relative;z-index:0;">C</div>

默认值规则
如果所有节点都定义了 position:relative。 z-index 为 0 的节点与没有定义 z-index 在同一层级内没有高低之分;但 z-index 大于等于 1 的节点会遮盖没有定义 z-index 的节点;z-index 的值为负数的节点将被没有定义 z-index 的节点覆盖。

<div id="a" style="position:relative;z-index:1;">A</div>
<div id="b" style="position:relative;z-index:0;">B</div>
<div id="c" style="position:relative;">C</div>
<div id="d" style="position:relative;z-index:0;">D</div>
```
![](http://upload-images.jianshu.io/upload_images/5275699-8aa5f14ed32c1c01.gif?imageMogr2/auto-orient/strip)
**从父规则**
如果 A,B 节点都定义了 position:relative,A 节点的 z-index 比 B 节点大,那么 A 的子节点必定覆盖在 B 的子节点前面。
```
<div id="a" style="position:relative;z-index:1;">
  <div id="a-1">A-1</div>
</div>
<div id="b" style="position:relative;z-index:0;">
  <div id="b-1">B-1</div>
</div>
```
![](http://upload-images.jianshu.io/upload_images/5275699-ff0542792504e903.gif?imageMogr2/auto-orient/strip)
 
如果所有节点都定义了 position:relative,A 节点的 z-index 和 B 节点一样大,但因为顺序规则,B 节点覆盖在 A 节点前面。就算 A 的子节点 z-index 值比 B 的子节点大,B 的子节点还是会覆盖在 A 的子节点前面。
![](http://upload-images.jianshu.io/upload_images/5275699-5eedaafdd55dfed4.gif?imageMogr2/auto-orient/strip)
#### position:relative 和 margin 的区别
position:relative,元素显示位置发生变化,但是元素在文档流中的位置不变,不影响后面元素在文档流中的布局。
margin,元素的显示位置和在文档流中的位置均发生变化,会影响后面元素在文档流中的位置。
#### BFC
BFC,块格式化上下文(block formatting context) 是Web页面的可视CSS渲染的一部分。它是块盒子的布局发生及浮动体彼此交互的区域。
**块格式化上下文由以下之一创建:**
1. 根元素或其它包含它的元素
2. 浮动 (元素的 float 不是 none)。
3. 绝对定位的元素 (元素具有 position 为 absolute 或 fixed)。
4. 内联块 inline-blocks (元素具有 display: inline-block)。
5. 表格单元格 (元素具有 display: table-cell,HTML表格单元格默认属性)。
6. 表格标题 (元素具有 display: table-caption, HTML表格标题默认属性)。
7. 块元素 (元素具有 overflow 值不是 visible)。
8. display: flow-root。

一个块格式化上下文包括创建它的元素内部所有内容,除了会创建新的块格式化上下文的元素。
块格式化上下文对于定位与清除浮动很重要。定位和清除浮动的样式规则只适用于处于同一块格式化上下文内的元素。浮动不会影响其它块格式化上下文中元素的布局,并且清除浮动只能清除同一块格式化上下文中在它前面的元素的浮动。
**[范例](http://jsbin.com/viwugaxahi/1/edit?html,css,output)**
#### 外边距合并问题
外边距合并指的是:当两个垂直外边距相遇时,它们将形成一个外边距。合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
**场景:**
当一个元素出现在另一个元素上面时,第一个元素的下外边距与第二个元素的上外边距会发生合并。
当一个元素包含在另一个元素中时(假设没有内边距或边框把外边距分隔开),它们的上和/或下外边距也会发生合并。
外边距甚至可以与自身发生合并。假设有一个空元素,它有外边距,但是没有边框或填充。在这种情况下,上外边距与下外边距就碰到了一起,它们会发生合并。如果这个外边距遇到另一个元素的外边距,它还会发生合并。
**为元素添加边框或者间距(border or padding)就可以不使边距重叠。**
[父子外边距合并范例](http://jsbin.com/quficofacu/1/edit?html,css,output)

【注】版权归 [Lucifer](http://www.jianshu.com/u/9849ba8ba63b) 所有,转载请联系作者。

推荐阅读更多精彩内容

  • 一,浮动元素有什么特征?对父容器、其他浮动元素、普通元素、文字分别有什么影响? 浮动模型是一种可视化格式模型,浮动...
    DeeJay_Y阅读 299评论 0 4
  • 浮动元素有什么特征?对父容器、其他浮动元素、普通元素、文字分别有什么影响? 特征: 元素脱离正常文档流,文字环绕图...
    1w1ng阅读 36评论 0 0
  • 1.浮动元素有什么特征?对父容器、其他浮动元素、普通元素、文字分别有什么影响? 浮动元素 浮动元素是设置float...
    Volcaner阅读 75评论 0 0
  • relative:生成相对定位的元素,通过top,bottom,left,right的位置相对于其正常位置进行定位...
    zx9426阅读 263评论 0 2
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 8,376评论 1 84