乐趣区

关于javascript:marginleft导致CSS中styleleft与offsetLeft取值数值上不等的情况

style.left & offsetLeft

<font size=”5px”>left</font> 是 css 款式中的一个属性,left 属性规定元素的左边缘。该属性定义了定位元素 <font color=red> 左外边距边界 </font> 与 <font color=red> 其蕴含块左边界 </font> 之间的偏移。(如果 “position” 属性的值为 “static”,那么设置 “left” 属性不会产生任何成果。)具体可参阅 W3C school

<font size=”5px”>offsetLeft</font> 是 HTML DOM Element 对象的一个属性,offsetLeft 属性返回 <font color=red> 以后元素左上角 </font> 绝对于 <font color=red>HTMLElement.offsetParent 节点的左边界 </font> 偏移的像素值。具体可参阅 MDN.

当然,style.left 返回的是带有 ”px” 的 可读写 字符串类型,offsetLeft 返回的是 只读 的数字型,本文中的比拟均是取 style.left 中的数字值。

代码示例

HTML 代码:

    <body>
    ![](images2/pikachu2.jpg)
    <button>btn</button>
    </body>

CSS 代码:

    <style>
        * {
            padding: 0;
            margin: 0;
        }

        img {
            position: relative;
            margin-left: 300px;
        }
    </style>

JS 代码:

<script>
    function Animate(el, targetP) {
        let currentP = el.offsetLeft  // 获取元素的以后地位
        let step = targetP > currentP ? 10 : -10  // 每次挪动 10px
        let animateTimer = setInterval(() => {
            currentP = el.offsetLeft  // 从新获取元素的以后地位
            el.style.left = currentP + step + "px"
            // 当指标地位和以后地位的间隔差的绝对值小于要挪动步数的绝对值时,间接挪动到指标地位并革除定时器
            if (Math.abs(targetP - currentP) < Math.abs(step)) {
                el.style.left = targetP + "px"
                clearInterval(animateTimer)
            }
        }, 15)
    }

    let image = document.querySelector("img")
    let btn = document.querySelector("button")
    btn.addEventListener("click", () => {Animate(image, 200)
    })

</script>

Animate(el, targetP)作用是将对应 DOM 元素程度挪动到指定地位。

Animate(image, 200)的目标是将图片程度挪动到 200px 的地位(因为咱们在图片上设了 300px 的 margin-left 值,所以预期的成果应该是图片左移 300-200=100px 的间隔),但实际上下面代码的运行后果是图片始终右移且永不进行。

从图片里咱们能够看到,当程序运行到 27 行断点处时,图片对象的 style.left 数值上是 0, 其 offsetLeft 值是 300;在程序运行到 30 行断点处时,图片对象的 style.left 数值上是 290, 其 offsetLeft 值是 590。持续执行程序咱们会发现,offsetLeft 值始终比 style.left 大 300。

这就是因为图片元素有 300px 的 margin-left 值,所以元素自身左上角的在间隔浏览器 300px 的绿色垂直线上,而元素自身的左外边距边界在浏览器左边缘的蓝色垂直线(画的很粗是为了突显那条线)上,从 HTML 中能够看到,图像元素的父级就是 body,所以它的父亲节点 / 蕴含图像的盒子就是 body 自身,body 的左边界在蓝色垂直线上,所以 style.left=0,而 offsetLeft 即 margin-left 的值 300;而在第二张图的 30 行断点处,通过 28 行后图像曾经程度挪动到 left=290px 即间隔第一张图片的绿色垂直线 290px 的地位,此时图片左上角间隔 body 的左边缘间隔(offsetLeft)为 300+290=590,所以两者值始终不相等。

代码示例批改后

那要怎么保障两者值相等呢?天然是要保障第一张图的蓝色和绿色在同一垂直线上,即图片的左外边距边界和图片的左上角位于同一垂直线上,也即去掉 margin-left 的值,如果切实想要 margin-left,也能够在图片的外层套一个绝对定位(position 默认值是 static,会导致 style.left 属性有效)的 div,把 margin-left 属性设置在该 div 上,这样一来图片左外边距边界、图片元素左边界、图片元素父元素左边界均在 div 的左边界上,就达到了咱们要的成果。

<head>
    <meta charset="UTF-8">
    <title> 测试 </title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        div {
            position: relative;
            margin-left: 300px;
            left: 50px;
        }
        img {position: relative;}
    </style>
</head>
<body>
<div>![](images2/pikachu2.jpg)</div>
</body>

js 局部代码不变。

论断

本文所探讨的状况下,以后元素的 <font color=red>margin-left</font> 属性若已设值,则 style.left 与 offsetLeft 在数值上不等,否则是相等的。

退出移动版