美文网首页让前端飞
offsetParent、offsetLeft/offsetTo

offsetParent、offsetLeft/offsetTo

作者: xshinei | 来源:发表于2018-12-22 21:35 被阅读1次

    element.offsetParent

    定义

    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:

    image

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

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

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

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

    <div class="box"></div>
    
    image

    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>
    
    image
    • 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>
    
    image

    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;
    }
    
    image

    打印element.offsetWidth:

    image

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

    • 有滚动条情况下
    image

    可以看到,滚动条包含在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

    image

    打印box.offsetLeft和box.offsetTop:

    image

    在文档流中,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:

    image

    两者的值都增加了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;
    }
    
    image

    打印box.offsetLeft和box.offsetTop:

    image

    两者的值又变化了!相比上次又增加了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:

    image

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

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

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

    我们打印下parent.offsetleft:

    image

    再计算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:

    image

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

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

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

    element.offsetLeft = element.left + element.marginLeft

    相关文章

      网友评论

        本文标题:offsetParent、offsetLeft/offsetTo

        本文链接:https://www.haomeiwen.com/subject/vqvwkqtx.html