定位及布局
信息流
浏览器在呈现信息时会按照元素的类型进行处理,它将块元素从上到下显示(块元素与块元素之间另起一行),将行内元素按语言方向水平显示(如汉字、英语是从左到右,维吾尔语、阿拉伯语等有些语言是从右到左),行内元素直到到达容器边缘时才换行显示,这种显示元素的方式叫做页面的正常流。
常见的大多数元素属于块元素,如 p
、table
、div
、li
、ul
、ol
、object
、h1-h6
等等,行内元素有 a
、span
、img
、b
、strong
等等。需要注意的是,匿名内容(即没有使用元素标签标注的内容)也按行内元素处理。
display
元素如何显示,可以通过 display
属性进行指定。每一个元素都有一个默认的 display
属性,但这个属性值可以修改。块元素和行内元素可通过 display
属性改变它们的显示方式,比如在某些情景,编辑人员需要给行内元素添加高度,以改进元素的显示效果,行内元素是无法直接通过 width
属性指定宽度的,但可以通过 display
属性将其变为块元素,再为其添加高度。
display
有很多属性值,最常用的是 block
、inline
、inline-block
以及 none
。其中 block
将元素按照块元素方式显示;inline
将元素按照行内元素显示;而 inline-block
模式将使元素像行内元素那样显示,但同时又具有 bolock
元素的特征,可以赋予宽度和高度等等;none
模式将元素整体隐藏起来,相当于该元素不存在一样,元素一旦声明其 display
的值为 none
,包含在内部的内容及其后代元素都会隐藏,并且其内容和后代不能再通过 display
改变显示方式。
浮动
除了相对定位和绝对定位能控制元素在正常流的位置之外,CSS 还提供了浮动(float)机制来控制元素在正常流中的位置,在实际工作中,float
属性是主要的定位、排版手段。从页面栏目的划分到图片的定位,大都通过 float
属性实现。
浮动的值有 left
、right
和 none
,其中左浮动将会使得块元素浮动向所在父元素的左侧,其后续的内容将出现在该元素的右侧,并和该元素的顶端对齐。右浮动刚好相反,none
则没有浮动效果。
先看一段 HTML 代码:
<!DOCTYPE html><html><head><meta charset="utf-8" /><title>浮动</title><style>#head { border:1px #CCC solid; width:410px; height:100px; margin-bottom:10px;}#main { border:1px #CCC solid; width:400px; height:200px; margin-bottom:10px; padding:5px;}#left { border:1px #CCC solid; width:198px; height:198px;}#right { border:1px #CCC solid; width:193px; height:198px; margin-left:5px;}</style></head><body><div id="head">头部</div><div id="main"> <div id="left">左侧</div> <div id="right">右侧</div></div></body></html>
这段代码的显示效果如下:

(\#fig:css-float-ex)浮动前的显示效果
下面,我们为 left
和 right
添加浮动属性。float 属性有三个值:none
(不浮动)、left
(左浮动)、right
(右浮动),其中 none
是默认值。盒元素必须为其指定明确的宽度值,才能应用浮动属性。在线演示案例
#left { border:1px #CCC solid; width:198px; height:98px; float:left;}#right { border:1px #CCC solid; width:193px; height:98px; margin-left:5px; float:left;}
显示效果如下:

(\#fig:css-floated)浮动效果
我们看到 id
为 right
的 div
元素现在和 id
为 left
的 div
元素在同一水平位置上显示,并非另起一行。浮动的方向是针对使用了浮动元素的位置而言的,并不应用于其后的元素。另外一定要注意,如果一个元素没有宽度大小,则不能指定浮动效果。
常见的图文混排效果,就是通过浮动来实现。
<div class="item"><div class="img_area"><a target="_blank" href="http://zhibo.qq.com/mbask/1844/index.html"><img src="http://t3.qlogo.cn/mbloghead/72f0353448bac74e1d86/50" alt="罗崇敏:安全不保 何谈教育" title="罗崇敏:安全不保 何谈教育"></a></div><div class="text_area"><h5>罗崇敏,中共云南省委高校工委书记,云南省教育厅长<a class="more" target="_blank" href="http://zhibo.qq.com/mbask/1844/index.html">[详细]</a></div><div class="item"><div class="img_area"><a target="_blank" href="http://zhibo.qq.com/mbask/1833/index.html"><img src="http://t3.qlogo.cn/mbloghead/ca99366b03bb20d692bc/50" alt="王旭明:如何避免校车惨剧一再发生" title="王旭明:如何避免校车惨剧一再发生"></a></div><div class="text_area"><h5><a target="_blank" href="http://zhibo.qq.com/mbask/1833/index.html">王旭明:如何避免惨剧再发生</a></h5>王旭明,教育部语文出版社社长,原教育部新闻发言人<a class="more" target="_blank" href="http://zhibo.qq.com/mbask/1833/index.html">[详细]</a></div>
在这个例子中,图片和文字分别作为内容放在 div
元素中,这两个 div
容器为“img_area
”和“text_area
”, “img_area
”和“text_area
”是 div
容器的类名称(使用了 class
属性),这两个 div
元素又是类名为 item
的容器的内容,类名为 item
的 div
元素可以重复使用,如上例中,就有两个类名为 item
的 div
元素。如果不使用浮动,文字没有办法完美环绕在图片周围,将图片放入类名为 img_area
的 div
元素中,并把文字放在类名为 text_area
的 div
元素中,使用如下样式,即可达到效果:
.img_area { float: left; padding: 3px 10px 0 0; width: auto;}.text_area { line-height: 20px;}.item { padding: 0 5px 5px; text-align: left;}
其中花括弧外面的“.img_area
”为选择符,.img_area
表示该选择符为类选择符,对应 HTML 中 class
为 img_area
的元素,“float:left
”表示选择符对应的元素将左浮动,“padding: 3px 10px 0 0;
”语句声明选择符对应元素上右下左的内边距分别为 3 像素、10 像素、0 和 0,最后 width
表示该元素的宽度将根据所包含内容的大小计算而来。另外两个 CSS 规则用来设定文字区域的行间距和整体的内边距、对齐方式。
在这个例子中,我们看到了浮动的特点,首先,类名为 img_area
的 div
元素声明了左浮动的规则,这样,这个 div
元素就改变了它默认的块元素显示方式,而是尽可能得向父元素(类名为 item
的 div
元素)的左上角靠齐,并且,它右侧的空间将会被后续的元素所填充,因此,尽管类名为 text_area
的 div
元素没有声明浮动,但它还是占据了类名为 img_area
元素的右侧空间。这样,我们就达到了图文混编的效果。
清除浮动
从上面的例子中,我们清楚地看到,使用了浮动属性的元素将会影响到其后的内容。这种影响有时候是我们期望的,有时候是我们所不乐见的。如下图所示:

(\#fig:css-beforeclear)清除浮动前
图中的 HTML 及 CSS 如下:
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>浮动清除实例</title><style type="text/css">body { font-size:14px; text-align:center;}.item { height:115px; width:500px; border:1px #ccc solid; padding:10px; margin:20px;}.float_area { border:1px #ccc solid; width:100px; float:left; margin:0 10px 10px 0;}.normal_area { border:1px #ccc solid; width:210px;}.float_area,.normal_area { height:50px; line-height:50px;}</style></head><body><div class="item"> <div class="float_area">左浮动模块</div> <div class="normal_area">希望按正常流显示的模块</div></div></body></html>
在上面的代码中,类名为 float_area
的 div
元素使用了左浮动,但是我们不希望类名为 normal_area
的 div
元素正常显示,也就是另起一行显示时,我们就必须使用 clear
属性来清除浮动,如下图所示。
clear
的值有 left
、right
、both
和 none
,其中 left
表示清除左浮动,right
表示清除右浮动,both
表示清除左、右两侧的浮动影响,而 none
表示不清除浮动。

(\#fig:css-clear)清除浮动
上图中的 HTML 和 CSS 如下:
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>浮动清除实例</title><style type="text/css">body { font-size:14px; text-align:center;}.item { height:115px; width:500px; border:1px #ccc solid; padding:10px; margin:20px;}.float_area { border:1px #ccc solid; width:100px; float:left; margin:0 10px 10px 0;}.normal_area { border:1px #ccc solid; width:210px; clear:both;}.float_area,.normal_area { height:50px; line-height:50px;}</style></head><body><div class="item"> <div class="float_area">左浮动模块</div> <div class="normal_area">希望按正常流显示的模块</div></div></body></html>
在本例中,我们需要类名为 normal_area
的 div
元素不和左浮动模块并排显示,而是另起一行,因此,我们为其声明了“clear:both”
的 CSS 规则,该规则表示将类名为 normal_area
的 div
元素不受之前左右浮动元素的影响,具体到上例中,“clear:both”
完全可以用“clear:left”
代替,显示效果是一致的。在线演示案例
除了上述的方法外,我们还可以在需要清除浮动的地方插入空白 div
,为其声明内嵌样式表,在样式表中声明 clear 属性即可。如下例所示:
<div class="item"> <div class="float_area">左浮动模块</div> <div style=”clear:both;”></div> <div class="normal_area">希望按正常流显示的模块</div></div>
这种方法对于初学者容易理解和掌握,但内容为空的 div
元素,在语义上并不十分完美,实际工作中广泛采用的是名为“clearfix”的一种技巧:
.clearfix:before,.clearfix:after { display: table; content: " ";}.clearfix:after { clear:both;}
这种 clearfix
方案,生成了两个伪元素,并将其 display
设置成 table
。这将创建一个匿名的 table-cell
和一个新的块状区域,这意味着::before
伪元素阻止了顶部边缘塌陷。而:after
伪元素清除了浮动。其结果是,只需要在包含浮动元素的容器上添加 class=“clearfix”
属性,没有必要专门添加 HTML
元素,减少清楚浮动所需的代码量,提高了工作效率。
在 CSS 中,和定位相关的常用属性有 position
、top
、right
、bottom
、left
、z-index
。通过这些属性,设计人员可以控制元素的精确定位。
position
position 属性用来设定对象的定位方式。它的值有:
- static 对象遵循常规流。
top
,right
,bottom
,left
等属性不会被应用,static
是position
属性的默认值。 - relative 对象遵循常规流,并且参照自身在常规流中的位置通过
top
,right
,bottom
,left
属性进行偏移时不影响常规流中的任何元素。 - absolute 对象脱离常规流,使用
top
,right
,bottom
,left
等属性进行绝对定位,盒子的偏移位置不影响常规流中的任何元素,其margin
不与其他任何margin
折叠。 - fixed 对象脱离常规流,使用
top
,right
,bottom
,left
等属性以窗口为参考点进行定位,当出现滚动条时,对象不会随着滚动。 - center 对象脱离常规流,使用
top
,right
,bottom
,left
等属性指定盒子的位置或尺寸大小。盒子在其包含容器垂直水平居中。盒子的偏移位置不影响常规流中的任何元素,其 margin 不与其他任何 margin 折叠。(CSS3 新增属性) - page 盒子的位置计算参照
absolute
。盒子在分页媒体或者区域块内,盒子的包含块始终是初始包含块,否则取决于每个absolute
模式。(CSS3 新增属性) - sticky 对象在常态时遵循常规流。它就像是
relative
和fixed
的合体,当在屏幕中时按常规流排版,当卷动到屏幕外时则表现如fixed
。该属性的表现是现实中你见到的吸附效果。(CSS3 新增属性)
其中 relative
和 absolute
方式使用较多,它们的区别可从下面的例子中看出:
<!DOCTYPE HTML><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>相对定位与绝对定位</title> <style type="text/css"> body { width:960px; margin: 0 auto; font-family: 微软雅黑; font-size: 18px; line-height: 1.8em; } div { width: 300px; float: left; } .relative { position: relative; top:150px; } .absolute { position: absolute; top:150px; } .bg { background-color: #fcc; } </style> </head> <body> <div> <h2>正常信息流</h2> <p>孩子,你真是快活啊,一早晨坐在泥土里,耍着折下来的小树枝。</p> <p>我微笑着看你在那里耍着那根折下来的小树枝。</p> <p class="bg">我正忙着算账,一小时一小时在那里加叠数字。</p> <p>也许你在看我,想到:“这种好没趣的游戏,竟把你的一早晨的好时间浪费掉了!"</p> <p>孩子,我忘了聚精会神玩耍树枝与泥饼的方法了。</p> </div> <div> <h2>相对定位</h2> <p>孩子,你真是快活啊,一早晨坐在泥土里,耍着折下来的小树枝。</p> <p>我微笑着看你在那里耍着那根折下来的小树枝。</p> <p class="bg relative">我正忙着算账,一小时一小时在那里加叠数字。</p> <p>也许你在看我,想到:“这种好没趣的游戏,竟把你的一早晨的好时间浪费掉了!"</p> <p>孩子,我忘了聚精会神玩耍树枝与泥饼的方法了。</p> <code>.relative { position: relative; top:150px;}</code> </div> <div> <h2>绝对定位</h2> <p>孩子,你真是快活啊,一早晨坐在泥土里,耍着折下来的小树枝。</p> <p>我微笑着看你在那里耍着那根折下来的小树枝。</p> <p class="bg absolute">我正忙着算账,一小时一小时在那里加叠数字。</p> <p>也许你在看我,想到:“这种好没趣的游戏,竟把你的一早晨的好时间浪费掉了!"</p> <p>孩子,我忘了聚精会神玩耍树枝与泥饼的方法了。</p> <code>.absolute { position: absolute; top:150px;} </code> </div> </body></html>
上例的运行结果在线演示案例如下图所示:

(\#fig:diff-positon)不同定位方式的区别
需要说明的是,absolute
方式定位的坐标原点默认为 body
元素的坐标原点,在上例中,使用绝对定位的元素虽然包含在第三个 div
元素中,但计算它的位置时,还是从 body
元素的顶部开始。
如果想要使 absolute
相对于所在父元素定位,则需要使父元素的 position
取值 relative
。如下例:
<!DOCTYPE HTML><html>
<head> <meta charset="utf-8"> <title>绝对定位的参照系</title> <style type="text/css"> body { width: 960px; margin: 0 auto; font-family: 微软雅黑; font-size: 18px; line-height: 1.8em; }
div { width: 400px; float: left; margin: 0 20px 0 0 }
.absolute { position: absolute; left: 50px; }
.bg { background-color: #fcc; }
code { background-color: #ccc; height: 50px; line-height: 50px; display: block; } </style></head>
<body> <div> <h2>以 body 为参照</h2> <p>孩子,你真是快活啊,一早晨坐在泥土里,耍着折下来的小树枝。</p> <p>我微笑着看你在那里耍着那根折下来的小树枝。</p> <p class="bg absolute">我正忙着算账,一小时一小时在那里加叠数字。</p> <p>也许你在看我,想到:“这种好没趣的游戏,竟把你的一早晨的好时间浪费掉了!"</p> <p>孩子,我忘了聚精会神玩耍树枝与泥饼的方法了。</p> <code>.absolute { position: absolute; left:50px;} </code> </div> <div> <div style="position:relative"> <h2>以父元素为参照</h2> <p>孩子,你真是快活啊,一早晨坐在泥土里,耍着折下来的小树枝。</p> <p>我微笑着看你在那里耍着那根折下来的小树枝。</p> <p class="bg absolute">我正忙着算账,一小时一小时在那里加叠数字。</p> <p>也许你在看我,想到:“这种好没趣的游戏,竟把你的一早晨的好时间浪费掉了!"</p> <p>孩子,我忘了聚精会神玩耍树枝与泥饼的方法了。</p> <code>.absolute { position: absolute; left:50px;} </code> </div> </div></body>
</html>
上例的运行结果见在线演示案例:

(\#fig:absolute-positon)不同定位方式的区别
top、right、bottom、left
top
、right
、bottom
、left
属性用来设置对象参照相对物顶边界向下、向左、向上、向右偏移的位置,这四个属性的值可以是正值,也可以是负值,可以是整数,也可以是百分比。必须定义 position
属性值为 relative
、absolute
、 fixed
、 center
、 page
,此属性方可生效。
top:50%;right:10px;bottom:100px;left:0;
clip
z-index
z-index
属性用来设置对象的层叠顺序。同一个层叠上下文中,层叠级别(即 z-index
属性值)大的显示在上面,反之显示在下面。该属性对定义了 position
为 relative
、 absolute
、 fixed
、 center
、 page
、 sticky
的元素有效,如果只设定 z-index
属性,但不使用 position
属性,则 z-index
属性无效。例如:
<!DOCTYPE HTML><html lang="zh">
<head> <meta charset="utf-8"> <title>z-index 属性演示</title> <style type="text/css"> body { width: 960px; margin: 0 auto; font-family: 微软雅黑; font-size: 18px; line-height: 1.8em; }
h1 { color: green; }
div { width: 100px; height: 100px; text-align: center; }
.index1 { position: absolute; left: 150px; top: 150px; background-color: #aaa; }
.index2 { background-color: #ccc; position: absolute; left: 190px; top: 190px; }
.index3 { position: absolute; left: 230px; top: 230px; z-index: 3; background-color: #eee; }
.index4 { z-index: 4; background-color: #999; } </style></head>
<body> <h1>z-index 属性只对使用了 position 属性的元素有效</h1> <div class="index4">z-index: 4</div> <div class="index1">z-index: 1</div> <div class="index2">z-index: 2</div> <div class="index3">z-index: 3</div></body>
</html>
上例中虽然为 div.index4
设定了 z-index
的值,但从运行效果(如下图所示)来看,这个 z-index
值显然没有起作用。在线演示案例

(\#fig:zindex)不同定位方式的区别
CSS 中的居中
前面已经介绍,文字水平居中的方法为:
text-align:center;
而元素的水平居中,通过设定 margin-left
和 margin-right
的值为 auto
实现,如:
margin:0 auto;
单行文字的垂直居中,通过设定文字的行间距等于容器高度可以实现,例如:
.center-text-trick { height: 100px; line-height: 100px;}
多行文字的的垂直居中,可通过利用表格的垂直居中属性 vertical-align
来实现,例如:
<div class="center-table"> <p>I'm vertically centered multiple lines of text in a CSS-created table layout.</p></div>.center-table { display: table; height: 250px; background: white; width: 240px; margin: 20px;}.center-table p { display: table-cell; margin: 0; background: black; color: white; padding: 20px; border: 10px solid white; vertical-align: middle;}
元素的垂直居中,在不知道元素高度的情况下,可以通过绝对定位来实现,例如在线演示案例:
<!DOCTYPE html><html>
<head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>元素垂直居中实例</title> <style> main { background: white; height: 300px; margin: 20px; width: 300px; position: relative; resize: vertical; overflow: auto; }
main div { position: absolute; top: 50%; left: 20px; right: 20px; background: black; color: white; padding: 20px; transform: translateY(-50%); resize: vertical; overflow: auto; } </style></head>
<body> <main> <div> 我是一个块级元素,高度未知,我在父元素中垂直居中。 </div> </main></body>
</html>
当我们不知道元素的宽度和高度时,可以使用如下的方法:
.parent { position: relative;}.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);}