CSS魔法堂:Absolute Positioning就这个样
前言
当我们以position:absolute之名让元素脱离Normal flow的控制后,以为通过left和top属性值即可让元素得以无限的自由时,却发现还有各种神秘的力量左右着它的来去,于是我们意识到自己力量的微弱,开始迷茫不前。
后来有幸拾到各路前辈高人的秘笈,终于打通任督二脉,记录在案以便日后查阅。
以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的宽度或高度。也就是得到以下两个等式:
- 垂直方向:
'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block - 水平方向:
'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时,实际值自动分配的情况
- top/height/bottom均不为auto时,那么margin-top/bottom两者的实际值相等,且足以满足等式1。
margin-top/bottom设置为auto时,实际值为0的情况
- top/height/bottom均为auto时,height的值由其子元素决定。top/bottom的值则根据虚拟盒子来决定,最终让定位效果如同采用
position:static一般,反正要让等式1成立。 - top/bottom均不为auto,而height为auto时,height会自动计算以满足等式1。
- 其他情况height由子元素或自身属性值决定,top/bottom由自身属性值或以满足等式1来决定实际值。
注意:top/auto/bottom默认值为auto,而margin-top/bottom默认值为0。
对于non-replaced element的水平方向等式
margin-left/right设置为auto时,实际值自动分配的情况
- left/width/right均不为auto时,那么margin-left/right两者的实际值相等,且足以满足等式2。
margin-left/right设置为auto时,实际值为0的情况
- left/width/right均为auto时,width的值由其子元素决定。left/right的值则根据direction的值来决定,最终让定位效果如同采用
position:static一般反,正要让等式2成立。 - left/right均不为auto,而width为auto时,width会自动计算以满足等式2。
- 其他情况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下会有以下例外:
- left/margin-left/margin-right/right均不为auto而width为auto时,IE5.5下width的实际值将由子元素决定;
- top/margin-top/margin-bottom/bottom均不为auto而height为auto时,IE5.5下height的实际值将由子元素决定;
- left/width/right均不为auto,而margin-left/right为auto时,IE5.5/6/7下margin-left/right的实际值为0;
- 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就这个样的更多相关文章
- CSS魔法堂:小结一下Box Model与Positioning Scheme
前言 对于Box Model和Positioning Scheme中3种定位模式的细节,已经通过以下几篇文章记录了我对其的理解和思考. <CSS魔法堂:重新认识Box Model.IFC.B ...
- CSS魔法堂:你一定误解过的Normal flow
前言 刚接触CSS时经常听到看到一个词"文档流",那到底什么是"文档流"呢?然后会看到"绝对定位和浮动定位能脱离文档流",从这句可以看到文 ...
- CSS魔法堂:说说Float那个被埋没的志向
前言 定位系统中第一难理解就是Normal flow,而第二就非Float莫属了,而Float难理解的原因有俩,1. 一开头我们就用错了:2. 它跟Normal flow靠得太近了.本文尝试理清Fl ...
- CSS魔法堂:Box-Shadow没那么简单啦:)
前言 说起box-shadow那第一个想法当然就是用来实现阴影,其实它还能用于实现其他好玩的效果的,本篇就打算说说box-shadow的那些事. 二话不说看效果 3D小球 <style typ ...
- CSS魔法堂:你真的懂text-align吗?
前言 也许提及text-align你会想起水平居中,但除了这个你对它还有多少了解呢?本篇打算和大家一起来跟text-align来一次负距离的交往,你准备好了吗? text-align属性详解 The ...
- CSS魔法堂:深入理解line-height和vertical-align
前言 一直听说line-height是指两行文本的基线间的距离,然后又说行高等于行距,最近还听说有个叫行间距的家伙,@张鑫旭还说line-height和vertical-align基情四射,贵圈真乱啊 ...
- CSS魔法堂:不得不说的Containing Block
前言 <CSS魔法堂:重新认识Box Model.IFC.BFC和Collapsing margins>中提到在没有floated兄弟盒子时,line box的左右边框会与所属的cont ...
- CSS魔法堂:hasLayout原来是这样!
前言 过去一直听说旧版本IE下很多诡异bug均由一个神秘角色引起的,那就是hasLayout.趁着最近突然发神经打算好好学习CSS,顺便解答多年来的疑惑. hasLayout到底是何方神圣? hasL ...
- CSS魔法堂:一起玩透伪元素和Content属性
前言 继上篇<CSS魔法堂:稍稍深入伪类选择器>记录完伪类后,我自然而然要向伪元素伸出"魔掌"的啦^_^.本文讲讲述伪元素以及功能强大的Contet属性,让我们可以通 ...
随机推荐
- nginx(1、正向代理)
正向代理是指客户端通过代理服务器访问某一个服务器,最常见的例子是内网用户通过代理访问外网,以及所谓的“FQ”. 在windows下实例如下: 1.下载安装包:nginx-1.7.9.zip: 2.解压 ...
- Windbg用法详解
工作空间 WinDBG的工作空间中保存了以下几种信息 调试会话状态: 包括断点,打开的源文件,用户定义的别名(alias)等. 调试器设置:包括符号文件路径,可执行映像文件路径,源文件路径,用I+/I ...
- 使用Guava提供的transform批量转换
实际开发了,为了快速查询,我们会把日期以Long类型的方式存储到数据库中,比如20000000000000L,但显示的时候,要完整的日期,即yyyy-MM-dd的格式显示. 这个时候,我们就可以使用C ...
- 值得使用的Spring Boot
2013年12月12日,Spring发布了4.0版本.这个本来只是作为Java平台上的控制反转容器的库,经过将近10年的发展已经成为了一个巨无霸产品.不过其依靠良好的分层设计,每个功能模块都能保持较好 ...
- Asp.net MVC 中Ajax的使用 [分享]
文章转自 http://www.huiyoumi.wang/upload/forum.php?mod=viewthread&tid=75&extra= Asp.net MVC 抛弃了A ...
- GDT,LDT,GDTR,LDTR 详解,包你理解透彻(转)
引自:http://www.techbulo.com/708.html 一.引入 保护模式下的段寄存器 由 16位的选择器 与 64位的段描述符寄存器 构成 段描述符寄存器: 存储段描述符 选择器:存 ...
- select2初始化默认值
之前用select2初始化默认值使用了select2('val','1'),这样做没问题,但只能用在单选上,多选的话,即使将val后面的值改成数组['0', '2']这种形式也没用. <scri ...
- Java连接Oracle数据库开发银行管理系统【三、实现篇】
说明:里面的主要代码都加的有注释部分,所以代码显得很长,如果有错误的地方,谢谢指出. 注意需要导入数据库jar包 ------------------------------------------- ...
- 删除顽固node_modules
在工作中有用到gulp,webpack,使用他们需用依赖node的一些模块包,于是会在目录下生成一个node_modules文件夹.有一次想删掉它重新生成模块包的时候发现根本不太可能,无穷无尽的报一个 ...
- Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结
Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结 1.1. 五中滤镜的分别效果..1 1.2. 基于肤色的图片分类1 1.3. 性能提升2 1.4. --co ...