美文网首页程序员
JS offset系列简明教程

JS offset系列简明教程

作者: 阿敏其人 | 来源:发表于2018-10-04 09:49 被阅读46次

    本文自出“阿敏其人”技术博客,转载请取得本人同意。


    一、offset团队的成员

    说起,offset,单词本身是偏移,补偿和位移的意思。
    JS中有一些offset方法/属性属性用于获取元素尺寸。

    打开像泰坦尼克一样的经典的北少林失传经典——W3c Element元素大全,我们发现,关于offset,大概有如下一些属性:

    属性 解释
    element.offsetHeight 返回元素的高度。
    element.offsetWidth 返回元素的宽度。
    element.offsetLeft 返回元素的水平偏移位置。
    element.offsetTop 返回元素的垂直偏移位置。
    element.offsetParent 返回元素的偏移容器。

    嗯,大道至简,言简意赅,简单到都不知道怎么区分了。
    不过,还是为芸芸众生指明了大的方向。那就是,宽高左上父类

    理解offset系列的时候,我们经常会和style样式的类似属性对对比。

    注意:
    ==offset系列属性都是 只读 的。==
    ==style.top、style.height之类的style系列的属性是 可读可写 的。==

    image.png

    二、offsetHeight和offsetWidth

    这对大兄弟,就是经典的宽和高了。
    他们非常类似,我们以 offsetWidth 例子展开描述。

    说起宽度,遥想过去,我们自然会想起css里面的style.width,既然有这个鬼东西存在了,那么还要offsetWidth来干嘛,字母比较长显得比较牛逼吗?

    显然不是,因为style.width有一定的弊端。

    css的style.width的弊端

    style.width只有在行内式的时候才可以获取到宽度。

    offsetWidth如何计算宽度

    计算方式

    offsetWidth = width + border + padding

    也就是,margin我不要,其他我都算。

    栗子,style.width和offsetWidth

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style type="text/css">
            body{
                background-color: #6C6C6C;
                margin:0;
                padding:0
            }
            #box1{
                width: 10px;
                height: 10px;
                padding: 20px;
                margin: 30px;
                border: 3px solid red;
            }
        </style>
    
    </head>
    <body>
    <div id="box1"></div>
    <div id="box2" style="width: 30px; height: 30px; border: 1px solid blue"></div>
    </body>
    <script>
        var box1 = document.getElementById("box1");
        console.log("box1 style.width: "+box1.style.width); // 输出空  style.width 只能得到行内式
        console.log("box1.offsetWidth: "+box1.offsetWidth); // 输出 56
        console.log("box1.offsetHeight: "+box1.offsetHeight); // 输出 56
        console.log("===");
        console.log("box2 style.width: "+box2.style.width); // 输出 30px
        console.log("box1.offsetWidth: "+box2.offsetWidth); // 输出 32
        console.log("box1.offsetHeight: "+box2.offsetHeight);  // 32
    </script>
    </html>
    

    .
    .
    效果:

    image.png

    .
    .

    offsetWidth小结图

    image.png

    .
    .

    三、offsetLeft和offsetTop

    我们的知道,在计算机的世界里,不上讲究上下左右,而是上左,下右之类的。
    有了宽高,加上top和left,就可以框定一个确定一个东西的大小和位置。

    说起offset的left和top,我们接着和style较劲,比如style.left。

    style.left的弊端

    只有在行内式定位的元素才有style.left。
    (只有行内样式的css的才能取到style.left的值)

    offsetLeft的计算

    offsetLeft:找到离元素最近的已经定位的父元素或祖先元素定位;如果没有,就根据根节点body定位,然后获取其left值。

    • 返回距离父元素(最近的带有定位)左边的位置(可以是间接父级)
    • 如果父元素都没有定位则以body 为准
    • ==offsetLeft 从父元素的padding 开始算,(不是父元素的border)==

    offsetLeft和offsetTop类似,我们以offsetLeft为例子展开描述,和style.left作对比。

    例子,offsetLeft 和 style.left

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style type="text/css">
            body{
                margin:0;
                padding:0
            }
            .grand{
                width: 300px;
                height: 300px;
                border: 7px solid gray;
                padding: 18px;
                background-color: red;
                position: relative;
            }
            .father{
                width: 200px;
                height: 200px;
                background-color: green;
                margin: 50px;
            }
            #son{
                width: 100px;
                height: 100px;
                background-color: blue;
                margin: 50px;
            }
            /*这样依然取不到style.left的值*/
            /*#son2{*/
                /*width: 100px;*/
                /*height: 100px;*/
                /*background-color: orange;*/
                /*margin: 50px;*/
                /*position: absolute;*/
                /*top: 6px;*/
                /*left: 6px;*/
            /*}*/
    
        </style>
    
    </head>
    
    <body>
    <div class="grand">
        <div class="father">
            <div id="son"></div>
            <div id="son2" style="width: 100px; height: 100px; background-color: orange; margin: 50px;
                position: absolute; top: 6px; left: 6px">
    
            </div>
        </div>
    </div>
    </body>
    
    <script>
        var son = document.getElementById("son");
        var son2 = document.getElementById("son2");
        console.log("son.offsetLeft: "+son.offsetLeft); // son.offsetLeft: 118
        console.log("son.style.left: "+son.style.left); // son.offsetLeft: 118
    
        console.log("son2.offsetLeft: "+son2.offsetLeft); // son2.offsetLeft: 56
        console.log("son2.style.left: "+son2.style.left); // son2.style.left: 6px   注意:style.left输出值是带px(如果有值)
    
    </script>
    </html>
    

    可以看出:
    确实是需要内行样式时,style.left才能取出时。
    style.left取出的是还有px后缀。
    style.left取出的值,是跟自己作比较,而不是跟父元素。

    son.offsetLeft显然是跟“父元素”作比较的。

    offsetLeft 和 offsetTop 小结图

    image-2.png

    .
    .

    四、offsetParent 获取父元素

    特点

    • 1、元素自身有fixed定位,offsetParent的结果为null
      • firefox并没有考虑固定定位的问题,返回<body>,其他浏览器都返回null
      • 当元素自身有fixed固定定位时,我们知道固定定位的元素相对于视口进行定位,
        此时没有定位父级,offsetParent的结果为null
    • 2、如果找到存在定位的父元素,offsetParent返回该父元素
    • 3、如果没有任何一个父元素(不断向上,找到为止)存在定位,offsetParent为body
    • 4、<body>元素的parentNode是null

    例子

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style type="text/css">
            /*如果自身为fixed,那么offsetParent为null*/
            /*.test{*/
                /*position: fixed;*/
            /*}*/
    
            .div0{
                position:absolute;
            }
    
    
            .div1{
                position: relative;
            }
    
        </style>
    
    </head>
    
    <body>
    <div id="div0" class="div0">
        <div id="div1" class="div1">
            <div id="test" class="test"></div>
        </div>
    </div>
    </body>
    
    <script>
        var test = document.getElementById("test");
        console.log(test.offsetParent);
        console.log(test.offsetParent.id);
        console.log(test.offsetParent.tagName);
    </script>
    </html>
    

    运行结果:

    image.png

    .
    .

    offsetParent 小结图

    image-3.png

    总结图

    image-4.png

    同系列相关文章:

    JS client系列简明教程
    JS scroll系列简明教程

    本文完。


    参考:
    深入理解定位父级offsetParent及偏移大小

    相关文章

      网友评论

        本文标题:JS offset系列简明教程

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