offsetParent、offsetLeft/offsetTop深度剖析

栏目: Html · 发布时间: 6年前

内容简介:element.offsetParent为包含element的祖先元素中,层级最近的定位元素。 也就是说,offsetParent必须满足三个条件:打印box元素的offsetParent:由此可见,box祖先元素中存在:

element.offsetParent为包含element的祖先元素中,层级最近的定位元素。 也就是说,offsetParent必须满足三个条件:

  • 是element的祖先元素
  • 最靠近element
  • 是定位元素,即position属性不为static
<div class="position-outer" style="position: relative;">
    <div class="position" style="postion: relative;">
        <div class="not-position">
        	<div class="box">
        	</div>
        </div>
    </div>
</div>
复制代码

打印box元素的offsetParent:

offsetParent、offsetLeft/offsetTop深度剖析

由此可见,box祖先元素中存在:

  • 层级为3的定位元素 position-outer
  • 层级为2的定位元素 position-inner
  • 层级为1的非定位元素 not-position

position-inner是同时满足层级最近和定位两个条件的。

祖先元素中不存在定位元素

<div class="box"></div>
复制代码
offsetParent、offsetLeft/offsetTop深度剖析

webkit内核、Firefox下的特殊情况

  • element自身的display属性为none
<div class="position-outer" style="position: relative;">
    <div class="position" style="postion: relative;">
        <div class="not-position">
        	<div class="box" style="display: none;"> <!-- 注意这里! -->
        	</div>
        </div>
    </div>
</div>
复制代码
offsetParent、offsetLeft/offsetTop深度剖析
  • element自身的position属性为fixed
<div class="position-outer" style="position: relative;">
    <div class="position" style="postion: relative;">
        <div class="not-position">
        	<div class="box" style="position: fixed;"> <!-- 注意这里! -->
        	</div>
        </div>
    </div>
</div>
复制代码
offsetParent、offsetLeft/offsetTop深度剖析

element.offsetWidth / element.offsetHeight

定义

offsetWidth = content + (垂直滚动条的宽度) + padding + border

  • 无滚动条情况下
<div class="box" style="">
</div>
复制代码
.box {
    width: 200px;
    height: 100px;
    padding: 20px;
    border: 12px solid red;
    margin: 25px;
}
复制代码
offsetParent、offsetLeft/offsetTop深度剖析

打印element.offsetWidth:

offsetParent、offsetLeft/offsetTop深度剖析

offsetWidth = 200(content) + 20 * 2(padding) + 12 * 2(border) = 264

  • 有滚动条情况下
offsetParent、offsetLeft/offsetTop深度剖析

可以看到,滚动条包含在padding中,因此,offsetWidth与在无滚动条情况下,大小不变。

element.offsetLeft / element.offsetTop

定义

element左上角相对于offsetParent左边界的偏移值。

有个疑问? element的左上角 与 offsetParent的左边界如何定义?是content-box、padding-box还是margin-box?

<div class="position">
    <div class="box">
    </div>
</div>
复制代码
.position {
    position: relative;
    top:  0;
    left:  0;
    width: 400px;
    height: 200px;
    padding:  35px;
    border: 15px solid purple;
}

.box {
    width: 200px;
    height: 100px;
    padding: 20px;
    border:  12px solid red;
    margin:  25px;
}
复制代码

很明显,box的offsetParent为postion

offsetParent、offsetLeft/offsetTop深度剖析

打印box.offsetLeft和box.offsetTop:

offsetParent、offsetLeft/offsetTop深度剖析

在文档流中,box的整个margin-box是在position的content-box中的,由此可猜测:

box.offsetLeft = position.paddingLeft + box.marginleft = 35 + 25 = 60

真的是这样吗?其实并没有那么简单,需要分两种情况讨论:

element在正常文档流中

element.offsetLeft是指element的border-box左上角相对offsetParent的content-box的偏移量

由于position: relative的元素并没有脱离文档流,因此,也需要加入到offseLeft/offsetTop的计算中

修改box css属性:

.box {
    position: relative; /* 新增的 */
    top: 31px;          /* 新增的 */
    left: 31px;         /* 新增的 */
    width: 200px;
    height: 100px;
    padding: 20px;
    border:  12px solid red;
    margin:  25px;
}
复制代码

再次打印box.offsetLeft和box.offsetTop:

offsetParent、offsetLeft/offsetTop深度剖析

两者的值都增加了31,也就是top和left属性对应的值,由此更新计算公式:

element.offsetLeft = offsetParent.paddingLeft + element.left + element.marginLeft

但是,以上都是在最简单的情况下计算的,即element与element.offsetParent之间没有其它层级的元素存在!

我们在element与element.offsetParent之间再插入一个元素:

<div class="position">
    <div class="middle">    <!-- 新增的 -->
        <div class="box">
        </div>
    </div>
</div>
复制代码
.parent {
    width: 30px;
    height: 150px;
    padding:  11px;
    border:  12px solid pink;
    margin-left:  13px;
}
复制代码
offsetParent、offsetLeft/offsetTop深度剖析

打印box.offsetLeft和box.offsetTop:

offsetParent、offsetLeft/offsetTop深度剖析

两者的值又变化了!相比上次又增加了36,正好是parent的marginLeft、borderLeft 、paddingLeft之和,11 + 12 + 13 = 36,由此得到最终的计算公式:

element.offsetLeft = offsetParent.paddingLeft + element.left + element.marginLeft + (element与element.offsetParent之间所有 在正常文档流且position属性不为relative的元素 marginLeft、borderLeft、paddingLeft之和)

element与element.offsetParent之间存在浮动元素

现在,我们让parent向右浮动:

.parent {
    float: right;
    width: 30px;
    height: 150px;
    padding:  11px;
    border:  12px solid pink;
    margin-left:  13px;
}
复制代码

打印box.offsetLeft和box.offsetTop:

offsetParent、offsetLeft/offsetTop深度剖析

这次只有box.offsetLeft变化了,而且也可以猜测到是由于parent的右浮,box是其子元素,一起右浮,导致box.offsetLeft变化的。

这下要怎么计算?难道还要算浮动的距离吗?

并不需要!只要借助parent就能计算!仔细想想,element与element.offsetParent一定是没有浮动元素的,那么对于parent,其offsetParent也就是box的offsetParent,即postition。

我们打印下parent.offsetleft:

offsetParent、offsetLeft/offsetTop深度剖析

再计算box到parent之间的偏移量: box.left + box.marginLeft + parent.paddingLeft + parent.borderLeft + parent.marginLeft = 31 + 25 + 11 + 12 + 13 = 92

76 + 92 = 168,与box.offsetLeft一致,这也说明我们的计算公式是正确的!

element脱离文档流

也就是说element的display属性为absolute或fixed,由于fixed会导致offsetParent为null,所以我们将box的display设置为absolute:

<div class="position">
    <div class="box">
    </div>
</div>
复制代码
.box {
    position: absolute; /* 新增的 */
    top: 31px;
    left:  31px;
    width: 200px;
    height: 100px;
    padding: 20px;
    border:  12px solid red;
    margin:  25px;
}

.position {
    position: relative;
    top:  0;
    left:  0;
    width: 400px;
    height: 200px;
    padding:  35px;
    border: 15px solid purple;
}
复制代码

打印box.offsetLeft和box.offsetTop:

offsetParent、offsetLeft/offsetTop深度剖析

我们知道,display属性为absolute或fixed的元素,是相对于包含块的padding-box定位的,因此在计算offsetLeft时,就不需要考虑offsetParent的paddingLeft了。

并且,element是脱离文档流的,也就是说,除了element.offsetParent,不再与其它任何元素产生联系,也就不需要再考虑element与element.offsetParent之间的任何元素了。

因此,计算公式非常简单:

element.offsetLeft = element.left + element.marginLeft


以上所述就是小编给大家介绍的《offsetParent、offsetLeft/offsetTop深度剖析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning Vue.js 2

Learning Vue.js 2

Olga Filipova / Packt Publishing / 2017-1-5 / USD 41.99

About This Book Learn how to propagate DOM changes across the website without writing extensive jQuery callbacks code.Learn how to achieve reactivity and easily compose views with Vue.js and unders......一起来看看 《Learning Vue.js 2》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具