定位界的NO.1 —— 绝对定位

1,923 阅读7分钟

说道最后一个了。绝对定位,这家伙在定位界中优先级别最高,但是用起来却并不复杂。

何为绝对定位box? 由position为absolute或fixed的dom元素产生的box,我们称之为绝对定位box。这类box是如何进行绝对定位的?position为absolute或是fixed会产生不同的效果吗?我们现在就去看看。

一. position为absolute的绝对定位box

用法:设置position为absolute,选定一个离它最近的父级定位box(第25条)作为它的containing block(第11条),利用left/right/top/bottom(用法请参考这里) 来相对containing block作一定的偏移(当然,你也可以不偏移)。

会不会有童鞋会问,如果绝对定位box没有父级定位box怎么办?嗯....有道理,是有可能出现的。

你要相信CSS开发小组!他们有设置备胎的。

如果绝对定位box没有父级定位box,那么它的containing block就是initial containing block(第10条)

二. position为fixed的绝对定位box

用法:设置position为fixed,以initial containing block作为它的containing block, 利用left / right / top / bottom 来相对containing block作一定的偏移。

特点:continuous media(看第1条)上,不管怎样滚动网页,该box的位置始终保持不变。道理很简单,因为initial containing block的位置是不会变化的!当然,如果某个position为absolute的box是以initial containing block为定位box,也会有同样的效果。

三. 实践中出真理

例一 left, top不为auto(适用于两种绝对定位box)

<html>
  <head>
  <style type="text/css">	
	*{
		padding:10px;
	}
	.parent{
		width:500px;
		height:150px;
		margin-top:50px;
		margin-left:auto;
		margin-right:auto;
		border:solid 2px #5CBDD2;	
	}
	.relative-child{
                position: relative;
		background-color: #5CBDD2;
	}
	.absolute-box{
		position: absolute;
		width:200px;
		height:50px;
		top:30px;
		left:50px;
		background-color: #E2D72F;
	}
  </style>
  </head>
<body>
<div class='parent'>
 	<div class='relative-child'>
 		I'm a relative box. I'm a relative box. I'm a relative box. I'm a relative box. 
 		<div class='absolute-box'>
 			I'm a absolute box
 		</div>
 	</div>
</div>
</body>
</html>

效果图:

很明显,绝对定位box相对它的父级定位box做了一定的偏移,按照代码里的设置,应该是向下偏移30px,向右偏移50px。

例二 left,right, top, bottom均为auto(适用于两种绝对定位box)

在例一的基础上,去掉absolute-box类中的left,top,修改成:

	.absolute-box{
		position: absolute;
		width:200px;
		height:50px;
		background-color: #E2D72F;
	}

再来看看效果:

没有作任何的偏移设置,绝对定位box竟然没有遮挡住文字。这。。。发生了什么?我们去调研一下。

该例去掉了对left及top的设置,故left, right, top, bottom均会取默认值auto。auto这个值,明显不是一个确定值,那在计算绝对定位box的位置时到底会设置成什么值呢?

这里涉及到高度计算规则。在CSS中,绝对定位box的高度需要满足以下等式:

' top' + 'margin-top' + 'border-top-width' + ' padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width '+ 'margin-bottom' + 'bottom' = height of containing block

如果top,bottom为auto,height不为auto,那么top将取“static position”时的值。什么叫static position? 就是假设该box的position为static,float为none,clear为none时其在普通流中的位置,此时top值为containing block(第11条)的上边缘到该box的上边缘的距离,而bottom只需等式相减即可得到。

同理,在计算绝对定位box的宽度时就会确定left及right的值。left取static position时的值,right取等式相减的结果。

因此,left、right、top、bottom为auto时,绝对定位box的位置就是它在普通流中的位置。

如果不相信,我们看看它变成普通流中的box的效果。

去掉absolute-box类中的position,修改成:

	.absolute-box{
		width:200px;
		height:50px;
		background-color: #E2D72F;
	}

登登登,效果如下:

绝对定位box的位置是不是和上图的一样。注意啊,我说的仅仅是位置,不是所有的都一模一样。有童鞋也许会说,父级定位box的高度变了。当然会变了,对于高度为auto的block-level box而言,计算高度时是不包含子box中绝对定位box的高度,所以它们不完全一样。

例三 父级定位box为inline box(只适用position为absolute的box)

inline box作为父级定位box时会稍有些特殊,这里单独示例一下。

先看源码:

<html>
  <head>
  <style type="text/css">	
	.parent{
		width:500px;
		height:150px;
		margin-top:50px;
		margin-left:auto;
		margin-right:auto;
		border:solid 2px #5CBDD2;		
	}
	.relative-child{
                position: relative;
		background-color: #5CBDD2;
	}
	.absolute-box{
		position: absolute;
		width:200px;
		height:50px;
		top:50px;
		left:50px;
		background-color: #E2D72F;
		text-align: center;
		line-height: 50px;
	}
  </style>
  </head>
<body>
<div class='parent'>
 	<span class='relative-child'>I'm a relative box. I'm a relative box. I'm a relative box.
 		<div class='absolute-box'>
 			I'm a absolute box
 		</div>
 	</span>
</div>
</body>
</html>

效果如下:

很正常对不对。其实,我是想告诉大家它背后隐藏的一条规则。

看过这篇文章的童鞋应该知道,inline box是需要放置在line box里的。不知道有木有人想过,如果一个inline box太长,一个line box放不下怎么办?此时,inline box会发生分裂(你要是通过不留空格的方式或其他方式阻止分裂,我也木有办法,这里仅讨论正常情况),变成多个inline box,且分别放置在相邻的line box中。如果没分裂前的inline box恰好是某个绝对定位box的父级定位box,因为空间不够进行分裂,就会出现多个符合条件的父级定位box的情况。

挑哪个?

以第一个inline box的上边缘(第24条)及左边缘作为绝对定位box的top及left的参考物。

增加上例中span的内容,具体修改如下:

<body>
<div class='parent'>
 	<span class='relative-child'>I'm a relative box. I'm a relative box. I'm a relative box. I'm a relative box. I'm a relative box. I'm a relative box. I'm a relative box. I'm a relative box. I'm a relative box.
 		<div class='absolute-box'>
 			I'm a absolute box
 		</div>
 	</span>
</div>
</body>

效果如下:

两个效果图对比一下,除了第二个图比第一个图多出两个inline box外,绝对定位box的位置并没有发生变化,它参考的始终是第一个inline box。

例四 父级定位box为initial containing block(适用于两种绝对定位box)


当position为absolute的绝对定位box没有父级定位box时,initial containing block就会充当这一角色(当然,这种情况始终适用于position为fixed的绝对定位box)。
<html>
  <head>
  <style type="text/css">	
	.parent{
		width:500px;
		height:150px;
		margin-top:50px;
		margin-left:auto;
		margin-right:auto;
		border:solid 2px #5CBDD2;	
	}
	.absolute-box{
		position: absolute;
		width:200px;
		height:50px;
		left:100px;
		top:100px;
		background-color: #E2D72F;
		padding:10px;
	}
  </style>
  </head>
<body>
<div class='parent'>
 		<div class='absolute-box'>
 			I'm a absolute box
 		</div>
</div>
</body>
</html>

效果就是酱紫:

上图中的绝对定位box参考的是initial containing box,因此相对左上角蓝点坐标为(50,50)。

四. 与浮动进行比较

他俩的共同点是: 都脱离了普通流。

不同点在于各自脱离的程度。

浮动虽然脱离了普通流,但它却在一定程度上影响着普通流box的布局,诸如一言不合就占据别人的地盘,挡住下方的block-level box,诱惑一堆文字围绕在旁等等。

而绝对定位,只会根据参照物去作一定的偏移,即使有时候会遮挡住其他box。它是从骨子里完全脱离了普通流,丝毫不会影响普通流box的布局!

总体看来,绝对定位是不是比浮动容易理解多了^ ^~~

写到这,其实很开心,终于系统的整理一遍了,期待自己能够再接再厉,接着出下个系列文章 *^ ^*!

ps: 本文中的例子均是在chrome 49.0上测试。