CSS浮动及定位
信息流
浏览器在呈现信息时会按照元素的类型进行处理,它将块元素从上到下显示(块元素与块元素之间另起一行),将行内元素按语言方向水平显示(如汉字、英语是从左到右,维吾尔语、阿拉伯语等有些语言是从右到左),行内元素直到到达容器边缘时才换行显示,这种显示元素的方式叫做页面的正常流。
常见的大多数元素属于块元素,如 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>
<div id="head">
<div id="main">左侧</div>
<div id="left">右侧</div>
<div id="right">
</div>
</body> </html
这段代码的显示效果如下:
下面,我们为 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;
}
显示效果如下:
我们看到 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
元素的右侧空间。这样,我们就达到了图文混编的效果。
清除浮动
从上面的例子中,我们清楚地看到,使用了浮动属性的元素将会影响到其后的内容。这种影响有时候是我们期望的,有时候是我们所不乐见的。如下图所示:
图中的 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
表示不清除浮动。
上图中的 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”
代替,显示效果是一致的。
使用codesandbox进行在线演示。
除了上述的方法外,我们还可以在需要清除浮动的地方插入空白 div
,为其声明内嵌样式表,在样式表中声明 clear 属性即可。如下例所示:
>
<div class="item">左浮动模块</div>
<div class="float_area":both;”></div>
<div style=”clear>希望按正常流显示的模块</div>
<div class="normal_area"> </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>
上例的运行结果如下图所示:
需要说明的是,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>
上例的运行结果见:
top、right、bottom、left
top
、right
、bottom
、left
属性用来设置对象参照相对物顶边界向下、向左、向上、向右偏移的位置,这四个属性的值可以是正值,也可以是负值,可以是整数,也可以是百分比。必须定义 position
属性值为 relative
、absolute
、 fixed
、 center
、 page
,此属性方可生效。
:50%;
top:10px;
right:100px;
bottom:0; left
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
值显然没有起作用。