JS | JS之元素偏移量 offset 系列属性详解

目录

一、offset 概述

定位父级

offsetParent 

偏移量

offsetWidth

offsetHeight

offsetLeft

offsetTop

计算页面偏移

注意事项

二、offset 与 style 区别

偏移offset

样式style

三、案例

★ 案例:获取鼠标在盒子内的坐标

★ 案例:模态框拖拽

★ 案例:仿京东放大镜

四、番外:元素视图方法


偏移量(offset dimension)是javascript中的一个重要的概念。涉及到偏移量的主要是offsetLeft、offsetTop、offsetHeight、offsetWidth这四个属性。当然,还有一个偏移参照——定位父级offsetParent。本文将详细介绍该部分内容。

一、offset 概述

offset 翻译过来就是偏移量, 我们使用 offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。

  • 获得元素距离带有定位父元素的位置

  • 获得元素自身的大小(宽度高度)

注意返回的数值都不带单位

♠ offset 系列常用属性 ♠

以上五个偏移量属性,它们都是只读属性。如果元素设置了display:none,则它的偏移量属性均为0。每次访问偏移量属性都需要重新计算,重复访问偏移量属性需耗费大量性能,如需重复访问,应将其值保存在变量中,以提高性能。 

参考分析图

示例代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }

      .father {
        margin: 100px;
        width: 200px;
        height: 200px;
        background-color: pink;
      }

      .son {
        margin-left: 30px;
        width: 100px;
        height: 100px;
        background-color: purple;
      }

      .box {
        margin: 0 100px;
        width: 200px;
        height: 200px;
        padding: 20px;
        background-color: skyblue;
        border: 10px solid red;
      }
    </style>
  </head>

  <body>
    <div class="father">
      <div class="son"></div>
    </div>
    <div class="box"></div>
    <script>
      // offset 系列
      let father = document.querySelector(".father");
      let son = document.querySelector(".son");

      // 1. offsetParent返回带有定位的父亲,否则返回的是body
      console.log(son.offsetParent); // 返回<body>...</body>
      // 注意:offsetParent与parentNode的值不一定相等
      // 返回最近一级的父亲(亲爸爸) 不管父亲有没有定位
      console.log(son.parentNode); // 返回<div class="father">...</div>

      // 2. 可以得到元素的偏移量(位置),返回的是不带单位的数值
      console.log(father.offsetTop); // 100 ,因为css为其设置的margin为100
      console.log(father.offsetLeft); // 100 ,因为css为其设置的margin为100
      // 它以带有定位的父亲为准,如果没有父亲或者父亲没有定位 则以 body 为准
      console.log(son.offsetLeft); // 130 ,因为虽然其有父亲,但是其父亲没有定位,所以以body为准,即100+30=130
     
     // 3. 可以得到元素的大小(宽度和高度),是包含padding + border + width/height的,不包括margin
      let box = document.querySelector(".box");
      console.log(box.offsetWidth); // 260
      console.log(box.offsetHeight); // 260
    </script>
  </body>
</html>

下面我们把offset的5个偏移属性,分别一一介绍一下

定位父级

offsetParent 

offsetParent属性是一个偏移参照,翻译为定位父级,即当前元素最近的有定位的父级元素(position不等于static)。定位父级分为下列四种情况。

在理解偏移大小之前,首先要理解offsetParent。人们并没有把offsetParent翻译为偏移父级,而是翻译成定位父级,很大原因是offsetParent与定位有关。

(1)当前元素自身有fixed定位,offsetParent返回null

当元素自身有fixed固定定位时,我们知道固定定位的元素相对于视口进行定位,此时没有定位父级,offsetParent的结果为null。

注意:firefox浏览器有兼容性问题——firefox没有考虑固定定位问题,返回body元素

<!-- 元素自身有fixed定位,offsetParent的结果为null -->
<div id="box" style="position:fixed;"></div>
<script>
    let box = document.querySelector('#box');
    console.log(box.offsetParent); // null
    //兼容问题:firefox浏览器没有考虑固定定位的问题,返回body元素,其他浏览器都返回null
</script>

(2)当前元素自身无fixed定位,且不存在有定位的父级元素,offsetParent返回body元素

<!-- 元素自身无fixed定位,且父级元素都未经过定位,offsetParent的结果为<body> -->
<div>
    <span id="box"></span>
</div>
<script>
    let box = document.querySelector('#box');
    console.log(box.offsetParent); // <body>...</boby>
</script>

(3)当前元素自身无fixed定位,且存在有定位的父级元素,offsetParent返回最近的有定位的父级元素

<!--元素自身无fixed定位,且父级元素存在经过定位的元素,offsetParent的结果为离自身元素最近的经过定位的父级元素-->
<div id="div0" style="position:absolute;">
  <div id="div1" style="position:absolute;">
    <span id="box"></span>
  </div>
</div>
<script>
    let box = document.querySelector('#box');
    console.log(span.offsetParent); // <div id="div1" style="position:absolute;">...</div>
</script>

(4)body元素无父元素节点,offsetParent返回null 

<!-- <body>元素的parentNode是null -->
<script>
    console.log(document.body.offsetParent); // null
</script>

★ IE7 浏览器Bug

对于定位父级offsetParent来说,IE7-浏览器存在以下bug

【bug1】元素本身经过绝对定位或相对定位,且父级元素无定位时,IE7-浏览器下offsetParent返回的结果是<html>

<div id="test" style="position:absolute;"></div>    
<script>
//IE7-浏览器返回<html>,其他浏览器返回<body>
let box = document.querySelector('#test');
console.log(box.offsetParent);
</script>
<div id="test" style="position:relative;"></div>    
<script>
//IE7-浏览器返回<html>,其他浏览器返回<body>
let box = document.querySelector('#test');
console.log(box.offsetParent);
</script>
<div id="test" style="position:fixed;"></div>    
<script>
// firefox并没有考虑固定定位的问题,返回<body>,其他浏览器都返回null
let box = document.querySelector('#test');
console.log(box.offsetParent);
</script>

 【bug2】如果父级元素存在触发haslayout的元素或有定位的元素,则offsetParent的结果为离自身元素最近的有定位或触发haslayout的父级元素

注意:关于haslayout的详细信息haslayout详解 - 小火柴的蓝色理想 - 博客园

<div id="div0" style="display:inline-block;">
    <div id='test'></div>    
</div>
<script>
let box = document.querySelector('#test');
//IE7-浏览器返回<div id="div0">,其他浏览器返回<body>
console.log(box.offsetParent);
</script>
<div id="div0" style="position:absolute;">
    <div id="div1" style="display:inline-block;">
        <div id='test'></div>    
    </div>    
</div>
<script>
let box = document.querySelector('#test');
//IE7-浏览器返回<div id="div1">,其他浏览器返回<div id="div0">
console.log(box.offsetParent);
</script>
<div id="div0" style="display:inline-block;">
    <div id="div1" style="position:absolute;">
        <div id='test'></div>    
    </div>    
</div>
<script>
let box = document.querySelector('#test');
//所有浏览器都返回<div id="div1">
console.log(box.offsetParent);
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

儒雅的烤地瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值