其实在之前的有一篇博客里已经写过了,但是这里还是要再详细描述下,因为它真的很重要啊
在前端工作中,position float的使用频率可以说非常的高,本文针对自己看博客以及平时工作遇到的问题的解决做一整理,希望对大家有所帮助
如果要掌握、运用好Position、Float属性必须要对HTML的两个基本点有清晰的了解。
盒子模型:box
在HTML元素的盒子模型分为两种;一种是块状元素(Block),一种是行内元素(Inline)。这里的块状元素与行内元素与display中的inline block是由区别的,盒子模型的inline block类似于是display的父亲,如Display属性中的list-item属性值是属于块状(Block)类型的
我们直观看两种盒子模型的区别
块状的元素可以设置width height等属性,而行内元素则不可以
块状元素独占一行,而行内元素则都会在一行内显示
块状元素的元素width默认为100%,而行内元素则是根据自身的内容以及子元素来决定宽度
块状元素:div p ul dd dt h1 h2 table address
行内元素: img span strong a input label select
HTML的普通流(normal flow)
浏览器在读取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>
代码改为:
<strong>strong</strong><em>em</em><span>span</span>
<div style="background: blue;">A</div>
<div style="background: red">B</div><strong>strong</strong>
<div style="background: green">C</div>
<strong>strong</strong><em>em</em><span>span</span>
<div style="background: blue;">A</div>
<div style="background: red;float:left;">B</div><strong>strong</strong>
<div style="background: green">C</div>
<strong>strong</strong><em>em</em><span>span</span>
<div style="background: blue;">A</div>
<div style="background: red;float:right;">B</div><strong>strong</strong>
<div style="background: green">C</div>
如果你不改变元素的默认样式前提下,元素在HTML的普通流中会“占用”一个位置,而“占用”位置的大小、位置则是由元素的盒子模型来决定。因此,在后续讲的Position、Float属性是否会使元素脱离这个普通流是一个关键点。
Position属性:
我们首先来谈谈Position属性,因为Position属性能够很好的体现HTML普通流这个特征。重点在于应用了不同的position值之后是否有脱离普通流和改变Display属性这两点。
Position属性值
Position的属性值共有四个static、relative、absolute、fixed。
static:
所有元素在 默认的情况下position1属性均为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有很多共同点:
- 会改变行内元素的呈现模式,使display之变更为block。
- 会让元素脱离普通流,不占据空间。
- 默认会覆盖到非定位元素上。
fixed与absolute最大的区别在于:absolute的”根元素“是可以被设置的,而fixed则其”根元素“固定为浏览器窗口。即当你滚动网页,其元素与浏览器窗口之间的距离是恒定不变的。
Float属性
float的属性值有none、left、right,有几个要点:
- 只有横向浮动,并没有纵向浮动。
- 当元素应用了float属性后,将会脱离普通流,其容器(父)元素将得不到脱离普通流的子元素高度。
- 会将元素的display属性变更为block。
- 浮动元素的后一个元素会围绕着浮动元素(典型运用是文字围绕图片),与应用了position的元素相比浮动元素并不会遮盖后一个元素。
- 浮动元素的前一个元素不会受到任何影响(如果你想让两个块状元素并排显示,必须让两个块状元素都应用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则可以清除浮动)。
常用的清除浮动的方法有两种:
- 通过在容器中添加一个标签,设置该标签的样式为 clear: both
- 容器设置overflow: hidden
<div style="background: #fff; width: 100%; overflow: hidden;"> <div style="float: left; position: absolute;">我是DIV</div> <div style="clear: both;"></div> <div>
关于文档流的问题
所谓的文档流,指的是元素排版布局过程中,元素会自动从左往右,从上往下的流式排列。
脱离文档流,也就是将元素从普通的布局排版中拿走,其他盒子在定位的时候,会当做脱离文档流的元素不存在而进行定位。
只有绝对定位absolute和浮动float才会脱离文档流。
---部分无视和完全无视的区别?需要注意的是,使用float脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本依然会为这个元素让出位置,环绕在周围(可以说是部分无视)。而对于使用absolute position脱离文档流的元素,其他盒子与其他盒子内的文本都会无视它。(可以说是完全无视)
[1]浮动-定义:浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。由于浮动框不在文档的普通流中,所以文档的普通流中的浮动框之后的块框表现得就像浮动框不存在一样。(注意这里是块框而不是内联元素;浮动框只对它后面的元素造成影响)
问题1:浮动元素后跟block元素&浮动元素后跟inline元素对布局的影响
浮动的框之后的block元素元素会认为这个框不存在,但其中的文本依然会为这个元素让出位置。 浮动的框之后的inline元素,会为这个框空出位置,然后按顺序排列。如下第一个例子box2是浮动框,其后跟一个块元素;例子2是浮动框后跟一个内联元素。
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1{background-color:pink;width:100px;height:100px;}
#box2{background-color:green;width:100px;height:100px;float:left;}
#box3{background-color:red;width:200px;height:200px;}
</style>
</head>
<body>
<div id="box1">box1</div>
<div id="box2">box2 向左浮动</div>
<div id="box3">box3</div>
<!--<span id="box3">span3</span>-->
</body>
问题2:元素浮动造成的两个div覆盖或相互重叠如何解决。
(1)、左右结构div盒子重叠现象,一般是由于相邻两个DIV一个使用浮动一个没有使用浮动。如上面的例1:相邻的两个盒子box2向左浮动、box3未浮动。一个使用浮动一个没有导致DIV不是在同个“平面”上,但内容不会照成覆盖现象,只有DIV形成覆盖现象。
解决方法:要么都不使用浮动;要么都使用float浮动;要么对没有使用float浮动的DIV设置margin样式。如上面的例1中box2宽度是100,只需要对box3设置margin-left:102px就可以实现不重叠。
(2)、上下结构div盒子重叠现象
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{margin:0;padding:0;}
.container{border:1px solid red;width:300px;}
#box1{background-color:green;float:left;width:100px;height:100px;}
#box2{background-color:deeppink; float:right;width:100px;height:100px; }
#box3{background-color:pink;height:40px;}
</style>
</head>
<body>
<div class="container">
<div id="box1">box1 向左浮动</div>
<div id="box2">box2 向右浮动</div>
</div>
<div id="box3">box3</div>
</body>
例子如上:.container和box3的布局是上下结构,上图发现box3跑到了上面,与.container产生了重叠,但文本内容没有发生覆盖,只有div发生覆盖现象。这个原因是因为第一个大盒子里的子元素使用了浮动,脱离了文档流,导致.container没有被撑开。box3认为.container没有高度(未被撑开),因此跑上去了。
解决方法:
1、要么给.container设置固定高度,一般情况下文字内容不确定多少就不能设置固定高度,所以一般不能设置“.container”高度(当然能确定内容多高,这种情况下“..container是可以设置一个高度即可解决覆盖问题。
2、要么清除浮动。清除浮动后的效果如下:
2-1:使用css clear清除浮动,在.container盒子闭合前加clear样式清除浮动。
深入理解clear属性:
clear属性规定元素的哪一侧不允许出现浮动元素,他的语法如下:
clear语法:
clear : none | left | right | both
取值:
none : 默认值。允许两边都可以有浮动对象
left : 不允许左边有浮动对象
right : 不允许右边有浮动对象
both : 不允许有浮动对象
但是需要注意的是:clear属性只会对自身起作用,而不会影响其他元素。如果一个元素的右侧有一浮动对象,而这个元素设置了不允许右边有浮动对象,即clear:right,则这个元素会自动下移一格,达到本元素右边没有浮动对象的目的。
务必记住这句话:“float是魔鬼,会影响其他相邻元素;但是clear是小白,其只会影响自身,不会对其他相邻元素造成影响!”
例如:下图例3 box1向右侧浮动,box2不设置clear属性时的示意图;例4中box1向右侧浮动,box2设置clear:right,表示右侧不允许出现浮动元素,则box2自动下移一行。
同样的,如果是box1向左浮动,box2和box1则会出现重叠,如例5;但如果在box2中设置clear:left;表示左侧不允许出现浮动元素,则box2同样会下移。
但是为了计算方便:一般都会增加一个空div块,并使用clear:both来设定表示两侧都不允许有浮动元素。这样新的空div块会下移,达到撑开父元素的目的。
<head>
<meta charset="UTF-8">
<title>DIV 相互重叠</title>
<style type="text/css">
*{margin:0;padding:0;}
.container{border:1px solid red;width:300px;}
#box1{background-color:green;float:left;width:100px;height:100px;}
#box2{background-color:deeppink; float:right;width:100px;height:100px; }
#box3{background-color:pink;height:40px;}
.clear{clear:both;}
</style>
</head>
<body>
<div class="container">
<div id="box1">box1 向左浮动</div>
<div id="box2">box2 向右浮动</div>
<div class="clear"></div>
</div>
<div id="box3">box3</div>
</body>
2-2:给父元素设置overflow:hidden来清除浮动。
这里我们可以这样理解:overflow:hidden的含义是超出的部分要裁切隐藏,float的元素虽然不在普通流中,但是他是浮动在普通流之上的,可以把普通流元素+浮动元素想象成一个立方体。如果没有明确设定包含容器高度的情况下,它要计算内容的全部高度才能确定在什么位置hidden,这样浮动元素的高度就要被计算进去。这样包含容器就会被撑开,清除浮动。
<head>
<meta charset="UTF-8">
<title>DIV 相互重叠</title>
<style type="text/css">
*{margin:0;padding:0;}
.container{border:1px solid red;width:300px;overflow:hidden;}
#box1{background-color:green;float:left;width:100px;height:100px;}
#box2{background-color:deeppink; float:right;width:100px;height:100px; }
#box3{background-color:pink;height:40px;}
.clear{clear:both;}
</style>
</head> <body>
<div class="container">
<div id="box1">box1 向左浮动</div>
<div id="box2">box2 向右浮动</div>
</div>
<div id="box3">box3</div>
</body>
[2]定位
分别分析一下position的几个值
(1)static 默认值,无定位,不能当作绝对定位的参照物,并且设置标签对象的left、top等值是不起作用的的。
(2)relative 相对定位。相对定位是相对于该元素在文档流中的原始位置,即以自己原始位置为参照物。有趣的是,即使设定了元素的相对定位以及偏移值,元素还占有着原来的位置,即占据文档流空间。(这里的占据文档流指的是占据原来的位置,而不是占据相对定位后的位置。个人理解:相对定位后的元素则会叠加到新位置的上,覆盖原先新位置上的元素,但是在新位置上不实际占据空间)如下图所示,头像相对定位前在box1盒子下方,头像相对定位后,头像原来的位置空着,但是下方的带有文本的盒子并没有移动上来。
这是相对定位的一个主要用法,图文混排。
注意,标签中设置了position:relative;属性,不设置left,right和top,bottom的值,这些值则默认值为0。注意,即使不设置值同样起到了相对定位作用,其子孙级别标签使用position:absolute;时同样会起到定位效果,position:relative的另一个主要用法:方便绝对定位元素找到参照物。
(3)绝对定位
定义:设置为绝对定位的元素框从文档流完全删除,并相对于最近的已定位祖先元素定位,如果元素没有已定位的祖先元素,那么它的位置相对于最初的包含块(即body元素)。元素原先在正常文档流中所占的空间会关闭,就好像该元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。
重点:如果父级设置了position属性,例如position:relative;,那么子元素就会以父级的左上角为原始点进行定位。这样能很好的解决自适应网站的标签偏离问题,即父级为自适应的,那我子元素就设置position:absolute;父元素设置position:relative;,然后Top、Right、Bottom、Left用百分比宽度表示。
总结:参照物用相对定位,子元素用绝对定位,并且保证相对定位参照物不会偏移即可。
绝对定位的层设好要参照位置的层后,就可以用TOP,LEFT这些来定位置了,如果它的上级或上上级都没定位的话只就会根据BODY的位置来定位了,还有最后一点,绝对定位是不占位置的,它会像PS的图层一样单独做一层,至于第几层你可以通过z-index:这个属性来设置。
另外要注意:仅使用margin属性布局绝对定位元素的情况
此情况,margin-bottom 和margin-right的值不再对文档流中的元素产生影响,因为该元素已经脱离了文档流。另外,不管它的祖先元素有没有定位,都是以文档流中原来所在的位置上偏移参照物。
图9中,使用margin属性布局相对定位元素。
层级关系为:
<div ——————————— position:relative;
<div—————————-没有设置为定位元素,不是参照物
<div———————-没有设置为定位元素,不是参照物
<div box1
<div box2 ——–position:absolute; margin-top:50px; margin-left:120px;
<div box3
效果图:
(4)fix定位
元素框的表现类似于将 position 设置为 absolute,不过其包含块是视窗本身。