深入理解css网页布局细节
在CSS网页开发布局中,需要对浮动和定位有深刻的理解才能在开发中游刃有余。
基于此,在博客园中做了本篇总结,这些总结来自实践经验和阅读一些书籍后的理解总结,主要内容为浮动,清除浮动,定位。
一. float属性深入理解
首先简单布局一下,代码如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>css Test</title> <style type="text/css"> #bigBox { border: 2px solid Gray; width: 500px; height: 400px; margin: 100px auto; } #box1{ background: yellow; width: 100px; height: 100px; } #box2{ background: SkyBlue; width: 120px; height: 100px; } #box3{ background: pink; width: 140px; height: 100px; } </style> </head> <body> <div id="bigBox"> <div id="box1">1</div> <div id="box2">2</div> <div id="box3">3</div> </div> </body> </html>
效果图:
图p1
1. 脱离文档流
脱离文档流,即在元素原来的位置中脱离出来,可以理解为漂浮起来,但是要注意一些细节。
细节一
若浮动元素后面有不浮动的元素,那么其后面不浮动的元素会把浮动元素视为消失,然后顶到它的位置中。
我们来测试一下:对第二个div(id=box2)设置浮动,观察第三个div的位置
#box1{ background: yellow; width: 100px; height: 100px; } #box2{ background: SkyBlue; width: 120px; height: 100px; float:left;/*测试内容*/ } #box3{ background: pink; width: 140px; height: 100px; }
效果图:
图p2
我们可以看到第三个div顶到浮动div原来的位置上去了,这里的float:left 设置为right,也同样,即第二个div消失了,后面的顶上去。
效果图:
图p3
细节二
我们不能理解为设置float之后,这个元素就完全漂浮在没有设置float元素的上面,虽然在细节一中的效果图中看是漂浮在上面(2在3的上面)。这个细节就是浮动只对后面的元素造成影响(所谓影响,就是后面的元素把它视为消失),对于排在它前面的同级块元素,不会对其位置造成影响。(即如果前面的同级块元素没有设置浮动,那么它也不会漂浮到这个元素的上面)。细节一的p1例子已经验证了这一特性(2还是在1的下面)。
那么,对于排在前面的同级内联元素呢?对于同级内联元素,设置了float属性的元素与前面的内联元素属于同一层面,而且优先级高于前面的同级内联元素,这里的优先级指位置优先级,比如float:left,那么前面的内联元素如果原来占据最左边,那么它由于优先级低于浮动元素,所以它就会让位与浮动元素,排在浮动元素的右边。
我们来看一下测试代码(重点查看注释的测试内容):
#box1{ background: yellow; width: 100px; height: 100px; display: inline-block; /*测试内容*/ } #box2{ background: SkyBlue; width: 120px; height: 100px; float:left; /*测试内容*/ } #box3{ background: pink; width: 140px; height: 100px; }
效果图:
图p4
分析:对于1(这里用数字代表相应的div,上下同)来说,由于排在浮动的2的前面,所以它无论是否为块元素,都和2属于同一层面,再由于它不是块元素,所以它的位置优先级别低于2,由于2的float:left,向左浮动,所以它靠最左,1被挤到它的右边。对于3来说,2由于是浮动,所以视为消失了,但是由于3是块元素,所以独占一行,于是就有了上面的效果。
细节三
文字永远会被挤出。我们把1,2设置浮动,把3注释,然后添加p标签。查看一下情况:
<div id="bigBox"> <div id="box1">1</div> <div id="box2">2</div> <!-- <div id="box3">3</div> --> <p>HelloWorld! HelloWorld! HelloWorld! HelloWorld! HelloWorld! HelloWorld! HelloWorld! HelloWorld! HelloWorld! HelloWorld! 10个HelloWorld!</p> </div>
图p5
实际上,并不是P元素和1,2浮动元素并列排在了一起,在细节一二中,我们知道p元素一定是顶到1的位置中的,但是由于文字永远是被挤出来的,所以他们被挤到2的左边,此时实现了一个文字环绕效果。我们可以给P元素添加背景色来查看一下实际:
p { background-color: red; }
图p6
2. 没有固定尺寸的父级元素无法自适应浮动的子元素(所有子元素都为浮动)
同样的,父元素属于文档流,如果子元素中有设置浮动的,那么也视为消失,所以父元素不会包裹它,如果全部子元素都为浮动,那么相当于这个父元素里面没有子元素,此时的表现和子元素为空一样。
我们先来看一下,在没有浮动元素的文档流中的情况:
代码:
body { margin: 0 300px; } #bigBox { border: 2px solid Gray; /* width: 500px; height: 400px;*//*测试内容:这里要设置去掉宽高*/ margin: 100px auto; } #box1{ background: yellow; width: 100px; height: 100px; } #box2{ background: SkyBlue; width: 120px; height: 100px; } #box3{ background: pink; width: 140px; height: 100px; }
<body> <div id="bigBox"> <div id="box1">1</div> <div id="box2">2</div> <div id="box3">3</div> </div> </body>
效果图:
图p7
这里的div(id=bigBox,1,2,3的父级元素)没有设置宽高,所以自动支撑起了子元素的宽高,由于1,2,3都是块元素,所以独占一行,宽度自动适应为body的宽度,所以如效果图所示,这是没有设置浮动的情况。
我们把2设置为浮动,查看一下效果:
#box2{ background: SkyBlue; width: 120px; height: 100px; float: left; /*测试内容*/ }
效果图:
图p8
父元素还是可以适应,不过视2为消失。
下面我们把全部子元素都设置为浮动,查看一下效果:
body { margin: 0 300px; } #bigBox { border: 2px solid Gray; /* width: 500px; height: 400px;*/ margin: 100px auto; } #box1{ background: yellow; width: 100px; height: 100px; float: left; /*测试内容*/ } #box2{ background: SkyBlue; width: 120px; height: 100px; float: left; /*测试内容*/ } #box3{ background: pink; width: 140px; height: 100px; float:left; /*测试内容*/ }
图p9
我们把1,2,3去掉,查看没有子元素的父元素的效果图,然后对比一下:
<body> <div id="bigBox"> <!-- <div id="box1">1</div> <div id="box2">2</div> <div id="box3">3</div> --> </div> </body> </html>
图p10
结果和p9是一样的,也就是p9中父元素把1,2,3视为消失了。
二. 清除浮动
1. 清除浮动方法(非父元素受影响)
方法一:设置clear属性,这个属性设置在受影响的元素(非父级)上
clear属性值有left,right,both,一般情况下对使用both清除浮动,我们来看一下:
#box1{ background: yellow; width: 100px; height: 100px; } #box2{ background: SkyBlue; width: 120px; height: 100px; float: left; /*测试内容*/ } #box3{ background: pink; width: 140px; height: 100px; clear:both; /*测试内容*/ }
图p11
请对比p2,可以这样形象理解,把原来2的消失变成了可见,然后就排在它的后面。
方法二:额外添加一个空元素,并设置clear属性
<div id="bigBox"> <div id="box1">1</div> <div id="box2">2</div> <div id="clear"></div> <!-- 测试内容 --> <div id="box3">3</div> </div>
#clear { clear: both; }
同样可以达到预期效果:
图p12
2. 清除浮动方法(父元素受影响)
图p7中我们看到父元素把子元素1,2,3视为消失,所以无法自适应子元素的宽度,为了消除子元素浮动对父元素的影响,这里有三个方法可以解决问题,我们来测试分析一下。
先把父元素受影响的代码和效果图贴出来:
图p13
方法一:在父元素里面添加一个空的子元素,放在最后面,并设置clear属性
<div id="bigBox"> <div id="box1">1</div> <div id="box2">2</div> <div id="box3">3</div> <!-- 这是一个清除浮动的空标签 --> <div id="clear"></div> </div>
效果图:
图p14
分析:原理很简单,空div设置了clear属性,所以它不受前面1,2,3的影响,所以它就会排在1,2,3的后面,造成了空div与顶部之间有了一定的距离,这个距离就拉大了父元素的尺寸,所以从表现上看,就像是清除了浮动,达到我们想要的效果。
此方法的弊端就是添加了额外的无意义的标签。
方法二:在父元素上设置overflow:hidden;
#bigBox { border: 2px solid Gray; /* width: 500px; height: 400px;*/ margin: 100px auto; overflow:hidden; /*测试内容*/ }
效果图:
图p15
深入理解overflow属性
overflow的属性值有:visible(默认值),hidden,scroll,auto,inherit
常用的是hidden属性,除了visible之外,不算inherit(继承)在内的其他三个属性值,如果设置了,那么该元素就会与浮动元素在同一个层面。我们可以看到文章开头的图p2中,2浮动在3的上面,因为它们不在同一个层面,如果对3设置overflow:hidden;(三个属性都可),那么他们就属于同一个层面,此时3虽然受浮动的影响,但是由于同一个层面的关系,所以它排在了2的后面,我们来测试一下。
#box1{ background: yellow; width: 100px; height: 100px; } #box2{ background: SkyBlue; width: 120px; height: 100px; float: left; /*测试内容*/ } #box3{ background: pink; width: 140px; height: 100px; overflow: hidden;/*测试内容*/ }
效果图:
图p16
我们比较图p2和p16,就可以看出overflow的这一特性。
回到我们讨论的父元素上面,父元素设置overflow属性,所以它就与所有浮动的子元素在同一层面上,所以就支撑了起来。不过它的弊端就是overflow的三个属性会对子元素超出父元素的部分不显示出来,可能造成信息缺失。
特别注意
在ie6及以下版本中(怪异模式),overflow的设置还是不起作用,这里就要用到ie特有的一个属性zoom来解决,只要设置zoom:1,即原来的大小即可,代码如下:
#bigBox { border: 2px solid Gray; /* width: 500px; height: 400px;*/ margin: 100px auto; overflow: hidden; zoom:1;/*添加这个属性,可兼容ie6*/ }
方法三:使用自定义伪类,设置清除属性
这是最实用和推荐的方法,一般把这个伪类的名称设置为 -XXX-clearFix,比如新浪微博就是用 -weibo-clearFix,在使用的过程中,我们习惯性的使用伪对象after的方法,在clearFix后面添加一些清除浮动的属性。
.-test-clearFix:after { clear: both; display: block; visibility: hidden; /*设置不可见*/ height: 0; line-height: 0; content: ""; /*after伪对象必须的属性,可以设置内容为空*/ } .-test-clearFix {}
在父级div里面添加这个类即可:
<div id="bigBox" class="-test-clearFix"> <div id="box1">1</div> <div id="box2">2</div> <div id="box3">3</div> </div>
效果图:
图p17
三. 相对定位和绝对定位
1. 相对定位
特点一
相对自身偏移。
相对定位比较好理解,它相对于自身进行了定位,所设置的偏移属性的参照物为本身原来的位置。
特点二
元素原来的位置不脱离文档流,占据了位置。
对于特点一、二,我们来测试一下:
#bigBox { border: 2px solid Gray; width: 500px; height: 400px; margin: 100px auto; } #box1{ background: yellow; width: 100px; height: 100px; float: left; } #box2{ background: SkyBlue; width: 120px; height: 100px; float: left; position: relative;/*测试内容*/ top: -140px; } #box3{ background: pink; width: 140px; height: 100px; float: left; }
图p18
2占据了原来的位置,所以3不会靠左移动。
2.绝对定位:absolute
特点一
脱离文档流
绝对定位和float属性有相似之处,设置了这个属性的元素会脱离文档流,脱离文档流后的表现和float一样,但是它无法清除浮动也不占据位置。
#bigBox { border: 2px solid Gray; /* width: 500px; height: 400px;*/ margin: 100px auto; position: relative; /*测试内容*/ } #box1{ background: yellow; width: 100px; height: 100px; position: absolute;/*测试内容*/ } #box2{ background: SkyBlue; width: 120px; height: 100px; position: absolute; /*测试内容*/ } #box3{ background: pink; width: 140px; height: 100px; position: absolute; /*测试内容*/ }
效果图:
图p19
图中可以看出1,2,3进行了绝对定位,并且重叠在了一起。其重叠特性为下面的特点二。
特点二
排再文档流后面的绝对定位元素显示的优先级高于前面的绝对定位元素。
为了区分,我们来给出一定的位移,观察前后优先级:
#bigBox { border: 2px solid Gray; /* width: 500px; height: 400px;*/ margin: 100px auto; position: relative; /*测试内容*/ } #box1{ background: yellow; width: 100px; height: 100px; position: absolute;/*测试内容*/ } #box2{ background: SkyBlue; width: 120px; height: 100px; position: absolute; /*测试内容*/ left: 50px; top:40px; } #box3{ background: pink; width: 140px; height: 100px; position: absolute; /*测试内容*/ left: 80px; top: 20px; }
图p20
图中可以看出优先级 3>2>1
特点三
绝对定位,其父级元素如果没有设置定位属性,则以更高级别的有设置定位属性的作为参照物进行定位,如果父级元素都没有定位属性,则以body作为参照。
(代码参考"特点一"中的代码#bigBox里面,设置了relative属性,里面的1,2,3以该父级元素进行绝对定位)
3. 绝对定位:fixed
这个定位属性是最简单的,其特点是脱离文档流,不占据位置,然后固定在屏幕,不会对文档流造成影响。这里就不进行代码验证。