关于设置了position:absolute的元素的位置设定:left和margin-left。困扰多时...诚向各位前辈请教!

实现一个自适应布局,效果图和HTML代码如下:
图片描述

<div class=”parent”>
<div class=”side”>侧栏</div>
<div class=”main”>主栏</div>
</div>
要求两栏间距为10px。
css代码如下:

.parent{font-size:22px;font-family:"微软雅黑";color:#fff;text-align: center;outline: 2px solid yellow;position: relative;line-height: 110px;}
.side{background-color:#c00000;width:200px;height:110px;}
.main{background-color:#4f81bd;position: absolute;right:0;top: 0px;bottom: 0px;left: 210px}

通过设置主栏div[class=main]的left:210,让它距离它父元素div[class=parent]左边框210px.
但是在这里,我突发奇想的尝试了另外一种情况:

.main{background-color:#4f81bd;position: absolute;right:0;top: 0px;bottom: 0px;left: 200px;margin-left: 10px}

我将left:210px换为了left:200px和margin-left:10px,居然实现了一样的效果:
·仅仅设置left:200px,如下图:
图片描述
·在设置了left:200px的基础上又设置了margin-left:10px,如下图:
图片描述
问题:div[class=main]在设置了position:absolute之后不是从文档流中脱离出来了吗?为何还可以操纵左外边距(margin-left)?甚至还真的和左边,在普通文档流中的div[class=side]的元素有10px的左边距?
希望各位大大不吝赐教!小子谢过~

阅读 14.5k
4 个回答

是脱离了文档流,但是margin-left是对他所在的层的(假设不同的流就是不同的层)所以 margin 是会起作用的。你可以设置side的margin 对main是没有影响的(测试他们是否在同一个层)

还有 absolute元素设置 上下左右值的时候 选择其中两个就好 比如上左,下右,下左,上右其中一个就好,

其实没有什么“为何”,文档里对此有明确的描述:

Absolutely positioned boxes can have margins, they do not collapse with any other margins.

至于你最后一句,那 10px 并不是针对 .side 的,和 .side 多大在哪里没有关系。你 absolute 之后设置了 left 200px,刚好等于 .side 的宽度,所以 margin 10px 之后看起来就和 normal flow 里设置边距的效果一样的,但其实没有什么关系,你可以把 .side 的宽度增加,或者设置 margin-right 试试就知道了。

http://segmentfault.com/a/1190000003820437#articleHeader9

OK,谈一下鄙见:

一方面,margin-left 的作用范围:

margin-left 在除了一些表格类元素上都是生效的,所以不要惊奇为什么绝对定位元素的 margin-left 有效。

另一方面,对“脱离文档流”的理解:

焦点在于元素的定位和大小的关系上:

  • 文档流内元素同其父元素以及同胞元素紧密相关

  • 脱离文档流的元素依赖于生成其包含块的元素

  • 脱离文档流的元素不影响生成其包含块的元素

  • 脱离文档流元素同其同胞元素一般没有直接关系

拓展来讲,由于元素的定位和大小计算是渲染中比较耗费效率的,比如用 margin width 等这些属性来做动画的时候,为了减少重排,最好就将其脱离文档流,这样被“波及”到的元素就少了。

当然,脱离文档流的元素在层叠上下文中的层级也会发生改变。但这和题主的问题没有太大关系。

现在来谈题主的问题。

  • PARENT 生成 MAIN 的包含块(此包含块为 PARENT 的内边距盒),所以 MAIN 的定位和大小是根据 PARENT 计算

  • MAIN 绝对定位后,和 SIDE 之间没有半毛钱关系,MAIN 的外边距对 SIDE 没有丝毫影响

  • MAIN 的 width 属性为默认值 auto,因此在计算这个 auto 值时候,必须满足这个约束方程式:(水平方向上)left + margin + border + padding + width + right = 包含块宽度,因此无论是 left: 210px 还是 left: 200px; margin-left: 10px 计算后 width 都一样一样的。

最后,题主这个问题涉及到的知识点有很多:

  1. 核心问题:绝对定位元素的宽度和外边距计算

  2. 关联问题:包含块 containing block 的定义、定位体系 positioning schemes

  3. 拓展问题:层叠上下文、浏览器原理与优化

所以之前才扔给题主一个链接……

个人鄙见,恳请斧正!

推荐问题
宣传栏