对CSS中的Position、Float属性的一些深入探讨

对 CSS 中的 Position、Float 属性的一些深入探讨

对于 Position、Float 我们在平时使用上可以说是使用频率非常高的两个 CSS 属性,对于这两个属性的使用上面可能大多数人存在一些模糊与不清晰的地方。本文主要对这两个属性使用上的一个介绍以及两个属性交叉使用上的一些探讨。

本文主要探讨点:

  1. Position、Float 属性的基本使用方法
  2. Position、Float 属性对元素所造成的影响
  3. Position、Float 属性交叉使用上面的影响
  4. Position、Float 属性使用上的小技巧

本文结构点:

  1. HTML 布局的基本要点(点我直接跳转)
      盒子模型
      HTML 的普通流
  2. Position 属性(点我直接跳转)
      属性值介绍
      用法介绍
      一些关于 position 的小知识
  3. Float 属性(点我直接跳转)
      属性值介绍
      用法介绍
      与 Position 之间的兼容问题

HTML 布局的基本要点:

如果要掌握、运用好 Position、Float 属性必须要对 HTML 的两个基本点有清晰的了解。

  1. 盒子模型(box model)
  2. HTML 的普通流(normal flow)

盒子模型

在 HTML 中元素的盒子模型分为两种:块状元素、行内元素,请注意这里的块状元素(Block)和行内元素(Inline)与 Display 属性中的 inline、block 两个属性值并不等同。盒子模型中的 Inline、Block 类似于是 Display 属性的父类,例如:Display 属性中的 list-item 属性值是属于块状(Block)类型的。

我们直观的上看两种盒子模型的区别

  • 块状(Block)类型的元素可以设置 width、height 属性,而行内(Inline)类型设置无效。
  • 块状(Block)类型的元素会独占一行(直观的说就是会换行显示,无法与其他元素在同一行内显示,除非你主动修改元素的样式),而行内(Inline)类型的元素则都会在一行内显示。
  • 块状(Block)类型的元素的 width 默认为 100%,而行内(Inline)类型的元素则是根据自身的内容及子元素来决定宽度。

列举出一些大家常见的元素的分类

  • 块状元素:P、DIV、UL、LI、DD、DT...
  • 行内元素:A、IMG、SPAN、STRONG...

HTML 的普通流

浏览器在读取 HTML 源代码的时候是根据元素在代码出现的顺序读取,最终元素的呈现方式是依据元素的盒子模型来决定的。行内元素是从左到右,块状元素是从上到下。(如下图)

<style type="text/css">
  div { width: 100px; height: 50px; line-height: 50px; text-align: center; color: #fff; }
  strong { background: #808080; }
  em { background: #ffd800; }
  span { background: #b6ff00; }
</style>
<strong>strong</strong><em>em</em><span>span</span>
<div style="background: blue">A</div>
<div style="background: red">B</div>
<div style="background: green">C</div>

如果你不改变元素的默认样式前提下,元素在 HTML 的普通流中会“占用”一个位置,而“占用”位置的大小、位置则是由元素的盒子模型来决定。因此,在后续讲的 Position、Float 属性是否会使元素脱离这个普通流是一个关键点

Position 属性:

我们首先来谈谈 Position 属性,因为 Position 属性能够很好的体现 HTML 普通流这个特征。重点在于应用了不同的 position 值之后是否有脱离普通流和改变 Display 属性这两点。

Position 属性值

Position 的属性值共有四个 static、relative、absolute、fixed。

Static

所有元素在默认的情况下 position 属性均为 static,而我们在布局上经常会用到的相对定位和绝对定位常用的属性 top、bottom、left、right 在 position 为 static 的情况下无效。其用法为:在改变了元素的 position 属性后可以将元素重置为 static 让其回归到页面默认的普通流中。

Relative

俗称的相对定位,重点在于对相对理解。我们此前说过每个元素在页面的普通流中会有“占用”一个位置,这个位置可以理解为默认位置,而相对定位就是将元素偏离元素的默认位置,普通流中依然保持着原有的默认位置,并没有脱离普通流,只是视觉上发生的偏移。
我们先用块状元素来做个示例:

<style type="text/css">
div{ width: 100px; height: 50px; line-height: 50px; text-align: center; color: #fff; }
</style>
<div style="background: blue">A</div>
<div style="background: red; position: relative; top: 20px; left: 20px;">B</div>
<div style="background: green">C</div>


右图中的黑色虚线部分为元素 B 的默认普通流位置,而黄色线则代表元素 B 的相对偏移量。我们可以很明显的看出在元素 C 依然还是保留在原位,并没有因为元素 B 发生了偏移而随之变化。

我们再来看看行内元素(在这里用大家最常用的 span 来做示例)

<style type="text/css">
strong { background: #808080; }
em { background: #ffd800; }
span { background: #b6ff00; position: relative; top: 10px; left: 10px; width: 100px; }
</style>
<strong>strong</strong><em>em</em><span>span</span>

请注意看,在这里我是有对 span 进行 width 属性的赋值(为 100px)。但是我们可以看到 span 在运用了 relative 这个 position 属性值后,依然对 width 属性无效,换而言之,position: relative 并没有改变行内元素的 Display 属性,这个概念非常重要(注意与接下来的 absolute 的区别)

 

Absolute

俗称的绝对定位,绝对定位是相对而言的,怎么理解呢?应用了 position: absolute 的元素会循着节点树中的父(祖)元素来确定“根”,然后相对这个“根”元素来偏移。如果在其节点树中所有父(祖)元素都没有设置 position 属性值为 relative 或者 absolute 则该元素最终将对 body 进行位置偏移。应用了 position: absolute 的元素会脱离页面中的普通流并改变 Display 属性(重点)

我们先用一个默认嵌套的 DIV 来做示例

<body style="background: yellow;">
    <div style="background: #fff">
        A
        <div style="background: #81b6ff">
            A - 1
            <div style="background: #b6ff00;">
                A - 2
            </div>
        </div>
    </div>
</body>

现在我们对 A-2 这个 div 设置绝对定位 (Top: 0, Left: 0),而没有对它的父元素(A、A-1)设置任何的 position 值

<body style="background: yellow;">
    <div style="background: #fff">A
        <div style="background: #81b6ff">A - 1
            <div style="background: #b6ff00; position: absolute; top: 0; left: 0;">
                A - 2</div></div></div></body>

可以看到(A-2)最终是根据 body 来产生了位移,让我们对比分别设置一下父元素 position。

从上面的图,我们可以总结以下几个结论。

1)块状元素在 position(relative/static) 的情况下 width 为 100%,但是设置了 position: absolute 之后,会将 width 变成 auto(会受到父元素的宽度影响)。

2)元素设置了 position: absolute 之后,如果没有设置 top、bottom、left、right 属性的话,浏览器会默认设置成 auto,而 auto 的值则是该元素的“默认位置”。即设置 position: absolute 前后的 offsetTop 和 offsetLeft 属性值不变。
特殊情况:

  • Firefox 的话会直接将 top、left 设置成 offsetTop 和 offsetLeft 的值而非 auto。
  • IE7 下的表现更类似于 float,会附加到父元素的末尾。

 

一些的 position 小知识

1)应用了 position: relative/absolute 的元素,margin 属性仍然有效,以 position:relative 来举例。如果设置了 left、top、bottom、right 的属性,建议大家不要设置 margin 数据,因为很难精确元素的定位,尽量减少干扰因素。

2)position: absolute 忽略根元素的 padding。

<div id="a" style="background: #fff; width: 200px;">A
    <div id="b" style="background: #81b6ff; width: 150px; position: relative; padding-top: 100px;">A - 1
        <div id="c" style="background: #b6ff00; position: absolute; left: 0; top: 0">A - 2
        </div>
    </div>
</div>

 

3)在 IE6/7 中设置 position 属性后会导致 z-index 属性失效

<!-- 解决方案,父元素设置一个更大的 z-index 值即可 -->
<div style="z-index: 2;">
  a
    <div style="position: relative; z-index: 1;">
      b
    </div>
</div>

4)行内元素在应用了 position:absolute 之后会改变 display。

<span style="position: absolute; width: 100px; height: 100px; top: 10px; left: 10px; background: #fff;">
        我的 display 属性由 inline 变成了 block
</span>


因此,要注意到 relative 是并没有改变行内元素的呈现模式,而 absolute 是会改变行内元素的呈现模式,如果设置了 absolute 并不需要显式的的将元素 display 改成 block。


5)应用了 position: absolute / relative 之后,会覆盖其他非定位元素(即 position 为 static 的元素),如果你不想覆盖到其他元素,也可以将 z-index 设置成 -1。

 

Fixed

在很长的时间里,这个属性值因为兼容性问题,并没有得到非常广泛的应用(IE6 未实现该属性值)。fixed 和 absolute 有很多共同点:

  1. 会改变行内元素的呈现模式,使 display 之变更为 block。
  2. 会让元素脱离普通流,不占据空间。
  3. 默认会覆盖到非定位元素上。

fixed 与 absolute 最大的区别在于:absolute 的”根元素“是可以被设置的,而 fixed 则其”根元素“固定为浏览器窗口。即当你滚动网页,其元素与浏览器窗口之间的距离是恒定不变的。

 

Float 属性

float 的属性值有 none、left、right,有几个要点:

  1. 只有横向浮动,并没有纵向浮动。
  2. 当元素应用了 float 属性后,将会脱离普通流,其容器(父)元素将得不到脱离普通流的子元素高度。
  3. 会将元素的 display 属性变更为 block。
  4. 浮动元素的后一个元素会围绕着浮动元素(典型运用是文字围绕图片),与应用了 position 的元素相比浮动元素并不会遮盖后一个元素。
  5. 浮动元素的前一个元素不会受到任何影响(如果你想让两个块状元素并排显示,必须让两个块状元素都应用 float)。

与 position 的兼容性问题

1)元素同时应用了 position: relative、float、(top / left / bottom / right)属性后,则元素先浮动到相应的位置,然后再根据(top / left / bottom / right)所设置的距离来发生偏移。

<div style="position:relative; float:right; left:50px; top:10px;">div</div>

左图中的 div 是没有设置 top、left 值的,而右边则设置了 50px 的偏移。

2)元素同时应用了 position: absolute 及 float 属性,则 float 失效。

<div style="position: absolute; right:10px; top: 10px; float: left;">
我是一个应用了 position:absolute 和 float:left 的 DIV,不过我还是在浏览器的右边,没有浮动到左边。
</div>


3)第一个元素应用了 position 之后会覆盖着接下来的 float 元素(如果两个元素所处的位置相同)

<div style="position: absolute; left:10px; top: 10px;">
    我是一个应用了 position:absolute 的 DIV。
</div>
<div style="float:left; background: red; width: 300px; height: 150px;">
    我是 float:left 的 DIV
</div>

回顾:如果你不将 float 的元素的 position 设置成 relative 的话,你想通过设置 float 元素的 z-index 来的达到覆盖 position:absolute 是无效的。同理,float 元素下面存在 position: absolute 的子元素,如果你不将 float 的元素的 position 设置成 relative 的话,absolute 元素是不会定位到 float 元素的。

4)同时应用 position: absolute 和 float: left 会导致清除浮动无效(position: relative 则可以清除浮动)。
常用的清除浮动的方法有两种:

  1. 通过在容器中添加一个标签,设置该标签的样式为 clear: both
  2. 容器设置 overflow: hidden
<div style="background: #fff; width: 100%; overflow: hidden;">
    <div style="float: left; position: absolute;">我是 DIV</div>
    <div style="clear: both;"></div>
<div>

 

最后,如果你觉得这篇文章对你有用的话。请帮忙点一下推荐,谢谢!^_^