前言

当我们以position:absolute之名让元素脱离Normal flow的控制后,以为通过lefttop属性值即可让元素得以无限的自由时,却发现还有各种神秘的力量左右着它的来去,于是我们意识到自己力量的微弱,开始迷茫不前。

后来有幸拾到各路前辈高人的秘笈,终于打通任督二脉,记录在案以便日后查阅。

以Normal flow为基础

Q:不是说好以左上角为原点(0,0)吗?怎么top:auto;right:auto;bottom:auto;left:auto;时的效果和Normal flow中的是一样的?

<style type="text/css">
#parent{
background: blue;
}
#sibling{
text-align: center;
line-height: 100px;
margin: 0 20px;
height: 100px;
background: red;
}
#protagonist{
text-align: center;
line-height: 100px;
width: 200px;
height: 100px;
background: yellow;
position: absolute;
}
</style>
<div id="parent">
<div id="sibling">position:static</div>
<div id="protagonist">position:absolute</div>
</div>



A:那是因为Absolute positioning在初始化状态时(top:auto;right:auto;bottom:auto;left:auto;),浏览器会生成一个看不见的采用Normal flow定位的虚拟盒子(hypothetical box),若虚拟盒子对应的盒子没有设置top/right/bottom/left属性值,则该盒子将与虚拟盒子重叠。

 因此当我们仅仅设置position:absolute时,呈现出来的效果是跟position:static是无区别的。那这时我们会有两个疑问了,1. 既然top/right/bottom/left等默认值为auto,那实际计算值是多少呢?2. 假如显示设置top/right/bottom/left为特定数值后,那效果又是如何的呢?

 若要回答上述问题,则先要理解定位参考系。一说起定位我们必须找到对应的参考系,如相对定位那样望文生义就知道它对应着某个参考系,而绝对定位则隐晦得多,咋看之下会让我们忽视参考系的重要性,然后糊里糊涂地理解和解读它呈现的效果。

 绝对定位的参考系就是盒子所在的containing block,下面我们来深入一下吧!

定位参考系——containing block

 不管采用的是Normal flow、Floats还是Absolute positioning,总之定位的参考系就是一个名为containing block的四方盒子,但不同的position scheme会对应不同containing block。就Absolute positioning而言,首先会寻找最近的一个position:relative/fixed/absolute的父容器元素,若找到且父容器为block-level element则以父容器的的padding box作为containing block,若父容器为inline-level element则根据父容器的directionCSS属性值决定containing block;若一个都找不到则会以initial containing block作为其的containing block。

更多关于containing block的信息可参考《CSS魔法堂:不得不说的Containing Block》

 因此top/right/bottom/left的实际值则是相对于containing block而言,我们可以通过el.offsetLeft/Top来获取top和left的实际值。

绝对定位的奥义——top/right/bottom/left+box model

也许大家都见过以下这种水平垂直居中方式(IE7/6/5.5下均无效)

    <style type="text/css">
#parent{
background: blue;
width: 200px;
height: 200px;
position: relative;
}
#protagonist{
background: yellow;
width: 100px;
height: 100px; position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
</style>
<div id="parent">
<div id="protagonist"></div>
</div>



为啥简单设置top/right/bottom/left:0;margin:auto就轻松搞定这么难搞的水平垂直居中呢?请看下图



 当盒子采用绝对定位后,其top/right/bottom/left和box model以占满整个containing block为目的,除非每个属性均设置的特定数值导致整体宽度或高度均小于containing block的宽度或高度。也就是得到以下两个等式:

  1. 垂直方向:'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block
  2. 水平方向:'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = width of containing block

     然后一切玄机则蕴藏在auto这个属性值上了。

    其中垂直方向上top/margin-top/height/margin-bottom/bottom可以设置为auto,而水平方向上则是left/margin-left/width/margin-right/right可以设置为auto。

对于non-replaced element的垂直方向等式

margin-top/bottom设置为auto时,实际值自动分配的情况

  1. top/height/bottom均不为auto时,那么margin-top/bottom两者的实际值相等,且足以满足等式1。

margin-top/bottom设置为auto时,实际值为0的情况

  1. top/height/bottom均为auto时,height的值由其子元素决定。top/bottom的值则根据虚拟盒子来决定,最终让定位效果如同采用position:static一般,反正要让等式1成立。
  2. top/bottom均不为auto,而height为auto时,height会自动计算以满足等式1。
  3. 其他情况height由子元素或自身属性值决定,top/bottom由自身属性值或以满足等式1来决定实际值。

注意:top/auto/bottom默认值为auto,而margin-top/bottom默认值为0。

对于non-replaced element的水平方向等式

margin-left/right设置为auto时,实际值自动分配的情况

  1. left/width/right均不为auto时,那么margin-left/right两者的实际值相等,且足以满足等式2。

margin-left/right设置为auto时,实际值为0的情况

  1. left/width/right均为auto时,width的值由其子元素决定。left/right的值则根据direction的值来决定,最终让定位效果如同采用position:static一般反,正要让等式2成立。
  2. left/right均不为auto,而width为auto时,width会自动计算以满足等式2。
  3. 其他情况width由子元素或自身属性值决定,left/right由自身属性值或以满足等式2来决定实际值。

注意:left/width/right默认值为auto,而margin-left/right默认值为0。

对于replaced element

 由于replaced element自身有固有的width/height,因此当设置width:auto;height:auto时,其实际值就是元素固有的width/height。也就是width/height不存在为满足等式2和1动态扩展/缩小实际值的情况。结果就是除"2. top/bottom均不为auto,而height为auto时,height会自动计算以满足等式1。"和"2. left/right均不为auto,而width为auto时,width会自动计算以满足等式2。"两条不满足外,其他情况均一致。

注意,IE5.5/6/7下会有以下例外:

  1. left/margin-left/margin-right/right均不为auto而width为auto时,IE5.5下width的实际值将由子元素决定;
  2. top/margin-top/margin-bottom/bottom均不为auto而height为auto时,IE5.5下height的实际值将由子元素决定;
  3. left/width/right均不为auto,而margin-left/right为auto时,IE5.5/6/7下margin-left/right的实际值为0;
  4. top/height/bottom均不为auto,而margin-top/bottom为auto时,IE5.5/6/7下margin-top/bottom的实际值为0.

Fixed positioning——Absolute positioning的子类

 对于position:fixed其实也属于Absolute positioning,但它参考系永远是由Viewport所产生的containing block而已,其他均与上述内容一致。

注意:由Viewport所产生的containing block与initail containing block是不同的详情请参考《CSS魔法堂:不得不说的Containing Block》

<style type="text/css">
body{
background: blue;
}
#protagonist{
background: yellow;
width: 100px;
height: 100px; position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
</style>
<div id="protagonist">fsjohnhuang</div>



注意:IE6不支持position:fixed

总结

若有纰漏,望各位指正,谢谢!

尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/5358587.html_肥子John

感谢

深入理解CSS绝对定位

10 Visual formatting model details

KB012: 绝对定位( Absolute positioning )

https://www.w3.org/TR/CSS21/visuren.html#fixed-positioning

CSS魔法堂:Absolute Positioning就这个样的更多相关文章

  1. CSS魔法堂:小结一下Box Model与Positioning Scheme

    前言  对于Box Model和Positioning Scheme中3种定位模式的细节,已经通过以下几篇文章记录了我对其的理解和思考.  <CSS魔法堂:重新认识Box Model.IFC.B ...

  2. CSS魔法堂:你一定误解过的Normal flow

    前言  刚接触CSS时经常听到看到一个词"文档流",那到底什么是"文档流"呢?然后会看到"绝对定位和浮动定位能脱离文档流",从这句可以看到文 ...

  3. CSS魔法堂:说说Float那个被埋没的志向

    前言  定位系统中第一难理解就是Normal flow,而第二就非Float莫属了,而Float难理解的原因有俩,1. 一开头我们就用错了:2. 它跟Normal flow靠得太近了.本文尝试理清Fl ...

  4. CSS魔法堂:Box-Shadow没那么简单啦:)

    前言  说起box-shadow那第一个想法当然就是用来实现阴影,其实它还能用于实现其他好玩的效果的,本篇就打算说说box-shadow的那些事. 二话不说看效果 3D小球 <style typ ...

  5. CSS魔法堂:你真的懂text-align吗?

    前言 也许提及text-align你会想起水平居中,但除了这个你对它还有多少了解呢?本篇打算和大家一起来跟text-align来一次负距离的交往,你准备好了吗? text-align属性详解 The ...

  6. CSS魔法堂:深入理解line-height和vertical-align

    前言 一直听说line-height是指两行文本的基线间的距离,然后又说行高等于行距,最近还听说有个叫行间距的家伙,@张鑫旭还说line-height和vertical-align基情四射,贵圈真乱啊 ...

  7. CSS魔法堂:不得不说的Containing Block

    前言  <CSS魔法堂:重新认识Box Model.IFC.BFC和Collapsing margins>中提到在没有floated兄弟盒子时,line box的左右边框会与所属的cont ...

  8. CSS魔法堂:hasLayout原来是这样!

    前言 过去一直听说旧版本IE下很多诡异bug均由一个神秘角色引起的,那就是hasLayout.趁着最近突然发神经打算好好学习CSS,顺便解答多年来的疑惑. hasLayout到底是何方神圣? hasL ...

  9. CSS魔法堂:一起玩透伪元素和Content属性

    前言  继上篇<CSS魔法堂:稍稍深入伪类选择器>记录完伪类后,我自然而然要向伪元素伸出"魔掌"的啦^_^.本文讲讲述伪元素以及功能强大的Contet属性,让我们可以通 ...

随机推荐

  1. nginx(1、正向代理)

    正向代理是指客户端通过代理服务器访问某一个服务器,最常见的例子是内网用户通过代理访问外网,以及所谓的“FQ”. 在windows下实例如下: 1.下载安装包:nginx-1.7.9.zip: 2.解压 ...

  2. Windbg用法详解

    工作空间 WinDBG的工作空间中保存了以下几种信息 调试会话状态: 包括断点,打开的源文件,用户定义的别名(alias)等. 调试器设置:包括符号文件路径,可执行映像文件路径,源文件路径,用I+/I ...

  3. 使用Guava提供的transform批量转换

    实际开发了,为了快速查询,我们会把日期以Long类型的方式存储到数据库中,比如20000000000000L,但显示的时候,要完整的日期,即yyyy-MM-dd的格式显示. 这个时候,我们就可以使用C ...

  4. 值得使用的Spring Boot

    2013年12月12日,Spring发布了4.0版本.这个本来只是作为Java平台上的控制反转容器的库,经过将近10年的发展已经成为了一个巨无霸产品.不过其依靠良好的分层设计,每个功能模块都能保持较好 ...

  5. Asp.net MVC 中Ajax的使用 [分享]

    文章转自 http://www.huiyoumi.wang/upload/forum.php?mod=viewthread&tid=75&extra= Asp.net MVC 抛弃了A ...

  6. GDT,LDT,GDTR,LDTR 详解,包你理解透彻(转)

    引自:http://www.techbulo.com/708.html 一.引入 保护模式下的段寄存器 由 16位的选择器 与 64位的段描述符寄存器 构成 段描述符寄存器: 存储段描述符 选择器:存 ...

  7. select2初始化默认值

    之前用select2初始化默认值使用了select2('val','1'),这样做没问题,但只能用在单选上,多选的话,即使将val后面的值改成数组['0', '2']这种形式也没用. <scri ...

  8. Java连接Oracle数据库开发银行管理系统【三、实现篇】

    说明:里面的主要代码都加的有注释部分,所以代码显得很长,如果有错误的地方,谢谢指出. 注意需要导入数据库jar包 ------------------------------------------- ...

  9. 删除顽固node_modules

    在工作中有用到gulp,webpack,使用他们需用依赖node的一些模块包,于是会在目录下生成一个node_modules文件夹.有一次想删掉它重新生成模块包的时候发现根本不太可能,无穷无尽的报一个 ...

  10. Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结

    Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结 1.1. 五中滤镜的分别效果..1 1.2. 基于肤色的图片分类1 1.3. 性能提升2 1.4. --co ...