探究offsetTop的取值

2019-06-13
JavaScript
6151

在网上搜offsetTop,说是距离父元素顶部的距离,感觉不是很清楚,这里来探究一下。

1. 是距离哪个父级元素的距离

创建一个如下demo

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>offset</title>
  <style>
    .parent {
      width: 200px;
      border: 3px solid #000;
      height: 300px;
    }
    .children {
      border: 3px  solid red;
      height: 200px;
    }
  </style>
</head>
<body>
  <div class="parent" id="parent">
    <div class="children" id="children"></div>
  </div>

  <script>
    console.log(document.getElementById('children').offsetTop)
  </script>
</body>
</html>

在chrome浏览器打开是11,竟然不是我想的0

所以,offsetTop应该是相对于此元素的第一个有定位的父元素,计算二者的距离差值。

如果给.prarent 加个 position: relative,立刻为0。

这里的11,是相对body元素(body有个初始化的padding值)。

2. 是否计算boder,padding,margin等位置

2.1 是否算border

如果给.prarent 加个 position: relative,offset变为0,可以推断出,offsetTop,是计算父元素boder以下,子元素boder以上的区域。

2.2 再给父元素加个padding

.parent {
      width: 200px;
      border: 3px solid #000;
      height: 300px;
      overflow: scroll;
      position: relative;
      padding-top: 20px;
}

发现,offsetTop值变为20,等于父元素padding-top的值

2.3 children元素上加个兄弟元素

 <style>
    .parent {
      width: 200px;
      border: 3px solid #000;
      height: 300px;
      overflow: scroll;
      position: relative;
      padding-top: 20px;
    }

    .sibling {
      height: 40px;
      background: wheat;
    }

    .children {
      border: 3px solid red;
      height: 500px;
    }
  </style>
<div class="parent" id="parent">
<div class="sibling"></div>
<div class="children" id="children"></div>
</div>

offset变为60,是父元素padding-topsibling的高度二者的和,

2.4 再将children设为绝对定位

.children {
      border: 3px solid red;
      height: 500px;
      position: absolute;
      top: 5px;
 }

offsetTop 变为5,这个很好理解,即相对父元素5px的偏移。

2.5 再将children设为相对定位

.children {
      border: 3px solid red;
      height: 500px;
      position: relative;
      top: 5px;
 }

offsetTop 变为65,这里应该是父元素padding-topsibling的高度以及相对自身5px的高度之和。

3. 滚动是否影响

代码修改如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>offset</title>
  <style>
    .parent {
      width: 200px;
      border: 3px solid #000;
      height: 300px;
      overflow: scroll;
      position: relative;
    }

    .children {
      border: 3px solid red;
      height: 500px;
    }
  </style>
</head>
<body>
<div class="parent" id="parent">
  <div class="children" id="children"></div>
</div>

<script>
    var childrenEl = document.getElementById('children');

    console.log('init offsetTop: ' + childrenEl.offsetTop);

    document.getElementById('parent').addEventListener('scroll', function () {
        console.log('scroll offsetTop: ' + childrenEl.offsetTop)
    });
</script>
</body>
</html>

可以发现,滚动过程中,两个值一直没有发生变化,因此,offsetTop 与滚动没有关系。

结论:

offsetTop,是计算第一个有定位的父元素boder一下,子元素border以上,这段距离。与是否滚动没有关系。