微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

探究:绝对定位没有设置 top, right, bottom, left 的世界是怎样的?

2015-09-01 19:27 前端大全

(点击上方,可快速关注)


作者:bolo的前端blog

网址:http://segmentfault.com/a/1190000003109367


一个元素如果设置了’position: absolute;’, 但没有设置top, right, bottom, left, 此元素的位置在哪?


在涉及到绝对定位元素的位置问题时, 一个重要的概念是containing block, 想要了解元素的位置, 还得找到此元素的containing block才行. 如下是我进行的一系列测试, 以及对测试结果的试探性解释.


文中的英文术语都不翻译, 方便直接查W3C或者其他技术文档.

请持有怀疑精神阅读此文, 欢迎讨论.


在inline box里的情况


http://jsfiddle.net/medifle/s00Laa0a/3

上面的例子没有对任何元素设置’position: absolute;’


http://jsfiddle.net/medifle/9qnp9uh4/1

增加如下代码


span.left {

margin-right: 10px;

padding-right: 10px;

}

span.inner {

position: absolute;

}


span.inner 只设置’position: absolute;’, 没有设置top, right, bottom或left. 此时top, right, bottom或left的initial value是auto.


现在, 尝试用chrome开发者工具对span.inner元素的’position: absolute;’进行勾选或者取消勾选, 看看发生了什么? (提醒: 在这个例子里, span.inner与span.left元素之间是没有空白符(white space)的, span.inner内部有一个空格, 两个 .)


取消勾选’position: absolute;’后, 多出一个空白符. 再次勾选后, 多出的那个空白符消失. 这个消失的空白符是谁? 为什么会消失?


现在我们先把span.inner的’position: absolute;’取消勾选. 如果我们再尝试对span.inner分别设置’float: left;’, ‘display: inline-block;’, ‘display: table-cell;’, ‘display: table;’, ‘display: inline-table;’, ‘display: inline-flex;’, 你会发现span.inner内的第一个空白符(是一个空格)都会发生同样的现象: 消失.


消失原因得从上面的一堆属性种找共同点: BFC(block formatting context). 上面的每一个属性(包括’position: absolute;’)都能够触发一个新的BFC, 所以span.inner里的内容进入了BFC后成为了新的一行, 而根据W3C的规范:


a sequence of collapsible spaces at the beginning of the line is removed


即行首部分的一个或多个可折叠(collapsible)的空白符是被移除的. 我想这就是消失的原因. 所以, 这个现象并不是’position: absolute;’没有设置top, right, bottom, left情况下的专属, 应该可以排除了.


注:


  • ‘overflow: hidden;’ 不能应用于inline box, 不满足触发BFC的条件. 详情见flow-root BFC

  • ‘display: table;’通过产生anonymous ‘table-cell’ box触发一个新的BFC.


从上面的例子里, 似乎span.inner的containing block的左边缘就是span.inner前面紧挨着的那个元素的margin右边缘. 情况是这样吗? 继续看下一个例子.


https://jsfiddle.net/medifle/t22sng4a/

此例中CSS未变, HTML的span.inner与span.left之间多了一个空白符, span.inner内部的第一个空白符(是个空格)去掉了, 留下了两个 .


<section class="demo">

<span class="left">Beginning of body contents.</span>

<span class="inner" style="position: absolute;">&nbsp;&nbsp;Inner contents.</span>

</section>


现在, 尝试用chrome开发者工具对span.inner元素的’position: absolute;’进行勾选或者取消勾选, 看看发生了什么?


这一次, 如果取消’position: absolute;’后再尝试对span.inner分别设置’float: left;’, ‘display: inline-block;’, ‘display: table-cell;’, ‘display: table;’, ‘display: inline-table;’, ‘display: inline-flex;’, 结果是: 没变化.


此例与上例的唯一改变就在于空白符的位置, 这说明了 span.inner的containing block的左边缘应该是span.inner前面紧挨着的那个元素(不考虑空白符)的margin右边缘. 并且left的initial value, 即’auto’, 会把span.inner定位到它的containing block的左边缘 (本文只考虑文本的’direction‘为’left-to-right’的情况).


https://jsfiddle.net/medifle/sccpersL/

html有改动, 加了两个图片, span与span元素之间没有空白符, 恢复span.inner的那个去掉的空白符(是个空格).


<section class="demo">

<p>

<span class="left">Beginning of body contents.</span><span class="inner" style="position: absolute;"> &nbsp;&nbsp;Inner contents.</span><img class="img1" src="https://upload.wikimedia.org/wikipedia/commons/e/e7/Mozilla_Firefox_3.5_logo_256.png" width="55"><img class="img2" src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Stack_Overflow_logo.svg/2000px-Stack_Overflow_logo.svg.png" width="300px">

</p>

</section>


现在测试的是span.inner(别忘了它只设置了’position: absolute;’且不设置top, right, bottom, left)的containing block的上边缘.


尝试用chrome开发者工具对span.inner元素的’position: absolute;’进行勾选或者取消勾选, 看看发生了什么?


span.inner在被赋予’position: absolute;’的时候, 其在垂直方向上的表现与对其设置’vertical-align: top;’没有差异. 从上述测试结果看, span.inner的containing block的上边缘应该与其所处的line box的content box的上边缘在位置上是一致的.


两个验证例子:

http://jsfiddle.net/medifle/3y7ucLLy/

http://jsfiddle.net/medifle/proa0fru/


对于上述的第二个例子, 尝试用chrome开发者工具对img.img1元素的’position: absolute;’进行勾选或者取消勾选, 看看发生了什么? (留意: img.img1和img.img2都设置了’position: absolute;’且没有设置top, right, bottom, left).


结果说明, 对一个元素(img.img1)进行绝对定位会影响到另一个绝对定位的元素(img.img2)的位置, 当然, 这个’绝对定位’是没有设置四个方向属性的值的情况.


http://jsfiddle.net/medifle/upg4da8o/

此例CSS变动如下:


.inbox {

color: blue;

position: absolute;

top: -10px;

}

.floatele {

float: right;

width: 300px;

height:50px;

background: tomato;

padding: 10px;

}

.demorel {

position: relative;

}


HTML如下:


<section class="demo demorel">

<p>Beginning of body contents.

<div class="floatele">

<span class="inner"> &nbsp;&nbsp;Inner contents.</span><span style="top: -10px;" class="inbox"> &nbsp;&nbsp;Inner contents.</span>

</div>

</p>

</section>


此例的第二个’Inner contents.’, 即span.inbox设置了top: -10px; 其他三个方向仍然不设置, 即为auto. section.demorel设置了’position: relative;’. div.floatele设置了’float: right;’, 此时span.inbox的containing block的左边缘仍然满足前面的结论.


在block box里的情况


http://jsfiddle.net/medifle/26dgo5k7/


<section class="demo demorel">

<div class="floatele">

<div class="inbox2"></div>

</div>

</section>


CSS主要有:


.inbox2 {

background: #6c4ecd;

width: 50px;

height: 50px;

position: absolute;

}

.floatele {

float: right;

width: 300px;

height:50px;

background: tomato;

padding: 10px;

}

.demorel {

position: relative;

}


div.inbox2的containing block的左边缘和上边缘都是其直系父元素content box的左边缘和上边缘 (content box的边缘又称content edge).


但值得注意的是, 此例与常规绝对定位情况下的区别:

http://jsfiddle.net/medifle/j7xevk78/


CSS有改变, 包含在HTML内:


<section class="demo demorel">

<div style="position: relative;" class="floatele">

<div style="left: 0; top: 0;" class="inbox2"></div>

</div>

</section>


这是一个常规的绝对定位例子, 因为设置了top和left的值. 值得注意的一点是, 此时div.inbox2的containing block的左边缘和上边缘是其直系父元素的padding edge.


小结


当绝对定位且不设置方向值的元素在inline box里时:


  1. 未设置的方向(top, right, bottom, left)的值是auto.

  2. 此元素containing block的左边缘应该是该元素前一个元素(空白符除外)的margin右边缘.

  3. 此元素containing block的上边缘应该是该元素所在的line box的content box的上边缘

  4. 如果left的值为auto, 则该元素会定位到其containing block的左边缘. 如果top的值为auto, 则该元素会定位到其containing block的上边缘.


当绝对定位且不设置方向值的元素在block box里时:


  1. 未设置的方向(top, right, bottom, left)的值是auto.

  2. 此元素的containing block的左边缘和上边缘应该是其父元素创建的content box的左边缘和上边缘.

  3. 如果left的值为auto, 则该元素会定位到其containing block的左边缘. 如果top的值为auto, 则该元素会定位到其containing block的上边缘.


本文只探讨了元素分别在line box和block box里的containing block的左边缘和上边缘(文本的’direction‘为默认的’ltr’, 即从左到右), 还有更多有待探讨.


本文所探讨的问题我没有找到直接相关的W3C规范, 如果有请一定要@bolo :)



前端大全

微信号:FrontDev

打造东半球最好的 前端技术 微信号

--------------------------------------

商务合作QQ:2302462408

投稿网址:top.jobbole.com

 
前端大全 更多文章 5个典型的JavaScript面试题(上) Limu:JavaScript的那些书 Web开发:我希望得到的编程学习路线图 JavaScript基础工具清单 常用排序算法之JavaScript实现
猜您喜欢 PostgreSQL中BRIN索引的存储结构 SQL数据库面试题以及答案 如何给你的女神修Mac电脑 数据挖掘工程师是做什么的? 前端福利,推荐10 个又短又小,但非常精悍的 JavaScript 代码段