深入理解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</span>:<span style="color: rgba(0, 0, 255, 1)">left</span>;<span style="color: rgba(0, 128, 0, 1)">/*<span style="color: rgba(0, 128, 0, 1)">测试内容<span style="color: rgba(0, 128, 0, 1)">*/</span></span></span>
}
#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</span>:<span style="color: rgba(0, 0, 255, 1)">left</span>; <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">测试内容</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
}
#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 视为消失,所以无法自适应子元素的宽度,为了消除子元素浮动对父元素的影响,这里有三个方法可以解决问题,我们来测试分析一下。
先把父元素受影响的代码和效果图贴出来:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>css Test</title> <style type="text/css">body {
margin: 0 300px;
}#bigBox {
border: 2px solid Gray;
/ width: 500px;
height: 400px;/
margin: 100px auto;
/clear: both;/
}#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; /测试内容/
}#clear {
clear: both;
}</style>
</head>
<body><div id="bigBox">
<div id="box1">1</div>
<div id="box2">2</div>
<div id="box3">3</div>
</div></body>
</html>
图 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</span>:<span style="color: rgba(0, 0, 255, 1)"> left</span>;<span style="color: rgba(255, 0, 0, 1)"> position</span>:<span style="color: rgba(0, 0, 255, 1)"> relative</span>;<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">测试内容</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(255, 0, 0, 1)"> top</span>:<span style="color: rgba(0, 0, 255, 1)"> -140px</span>;
}
#box3{
background: pink;
width: 140px;
height: 100px;float</span>:<span style="color: rgba(0, 0, 255, 1)"> left</span>;
}
图 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
这个定位属性是最简单的,其特点是脱离文档流,不占据位置,然后固定在屏幕,不会对文档流造成影响。这里就不进行代码验证。
深入理解了这些属性,就可以在实际工作中灵活应用,后续会总结一些布局实战。本文若有不妥之处,欢迎批评指正。