clientHeight offsetHeight scrollHeight offsetTop scrollTop

article/2025/10/22 16:01:27

文章目录

  • 各属性详解
      • 实现
  • offsetParent、offsetLeft/offsetTop深度剖析
  • element.offsetParent
    • 定义
    • 祖先元素中不存在定位元素
    • webkit内核、Firefox下的特殊情况
  • element.offsetWidth / element.offsetHeight
    • 定义
  • element.offsetLeft / element.offsetTop
    • 定义
    • element在正常文档流中
      • element与element.offsetParent之间存在浮动元素
    • element脱离文档流

每个HTML元素都具有clientHeight offsetHeight scrollHeight offsetTop scrollTop 这5个和元素高度、滚动、位置相关的属性,单凭单词很难搞清楚分别代表什么意思之间有什么区别。通过阅读它们的文档总结出规律如下:

各属性详解

clientHeight和offsetHeight属性和元素的滚动、位置没有关系它代表元素的高度,其中:
clientHeight:包括padding但不包括border、水平滚动条、margin的元素的高度。对于inline的元素这个属性一直是0,单位px,只读元素。

请添加图片描述

offsetHeight:包括padding、border、水平滚动条,但不包括margin的元素的高度。对于inline的元素这个属性一直是0,单位px,只读元素。

请添加图片描述

接下来讨论出现有滚动条时的情况:
当本元素的子元素比本元素高且overflow=scroll时,本元素会scroll,这时:
scrollHeight: 因为子元素比父元素高,父元素不想被子元素撑的一样高就显示出了滚动条,在滚动的过程中本元素有部分被隐藏了,scrollHeight代表包括当前不可见部分的元素的高度。而可见部分的高度其实就是clientHeight,也就是scrollHeight>=clientHeight恒成立。在有滚动条时讨论scrollHeight才有意义,在没有滚动条时scrollHeight==clientHeight恒成立。单位px,只读元素。
在这里插入图片描述

scrollTop: 代表在有滚动条时,滚动条向下滚动的距离也就是元素顶部被遮住部分的高度。在没有滚动条时scrollTop==0恒成立。单位px,可读可设置。
offsetTop: 当前元素顶部距离最近父元素顶部的距离,和有没有滚动条没有关系。单位px,只读元素。
在这里插入图片描述offsetTop: 当前元素顶部距离最近父元素顶部的距离,和有没有滚动条没有关系。单位px,只读元素。

在这里插入图片描述

  • 网页可见区域高:document.body.clientHeight //返回元素的高度(包括元素高度、内边距,不包括边框和外边距)

  • 网页正文全文高:document.body.scrollHeight //返回元素的高度(包括元素高度、内边距和溢出尺寸,不包括边框和外边距),无溢出的情况,与clientHeight相同

  • 网页可见区域高(包括边线的高):document.body.offsetHeight //返回元素的高度(包括元素高度、内边距和边框,不包括外边距)

  • scrollTop //此属性可以获取或者设置对象的最顶部到对象在当前窗口显示的范围内的顶边的距离,也就是元素滚动条被向下拉动的距离。 返回值是一个整数,单位是像素。此属性是可读写的

  • 网页被卷去的高:document.body.scrollTop

  • 屏幕分辨率高:window.screen.height

  • style.height //返回元素的高度(包括元素高度,不包括内边距、边框和外边距)

  • offsetTop //返回元素的上外缘距离最近采用定位父元素内壁的距离,如果父元素中没有采用非静态定位的,则是获取上外边缘距离body的距离。


下面是理解应用
(在IOS移动端上,当使用overflow: scroll;属性时,滚动效果慢且不流畅,该情况可以使用

-webkit-overflow-scrolling: touch;属性,让滚动条产生回弹效果,增加滚动的流畅性,提高用户的体验。)。在手指在移动设备的触摸屏上滑动的过程中,监听手指开始滑动,滑动过程中及滑动结束3个事件。在滑动中事件中检查当前滑动的位置是否到达滚动区域的底部,若已到达底部则停止滑动。

实现

给滑动区域添加手势触摸的相关事件

<div @touchstart="touchStart" @touchmove="touchMove" @touchEnd="touchEnd"><!-- 这是一个滚动区域 -->
</div>

定义一个变量用来记录上一次手势滑动过程中最新位置的纵坐标值

export default {data () {lastScrollY: 0 // 上一次手势滑动过程中最新位置的纵坐标}
}

通过手势滑动过程中出发的事件监听滚动区域是否已经到达底部

export default {methods: {touchStart(e) {// 滑动开始时记录起始位置纵坐标this.lastScrollY = e.touches[0].clientY},touchMove(e) {// 滑动过程中记录当前位置纵坐标let top = e.touches[0].clientY// 当前滚动条距离顶部的距离let scrollTop = e.currentTarget.scrollTop// 判断滚动条滚动的方向let direction = (this.lastScrollY - top) < 0 ? 'up' : 'down'// (若滚动条距离顶部的距离 >= 滚动区域的高度 - 滚动可视区域的高度) && 滚动条滚动方向向下 :已到达滚动区域的底部if (scrollTop >= (e.currentTarget.scrollHeight - e.currentTarget.offsetHeight) && direction === 'down') {// 取消事件的默认行为e.preventDefault()// 还原记录的坐标值this.lastScrollY = 0} else {// 否则更新记录的当前位置纵坐标this.lastScrollY = top}},touchEnd() {// 每一次滑动结束时还原记录的坐标值this.lastScrollY = 0}}
}

offsetParent、offsetLeft/offsetTop深度剖析

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:

img

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

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

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

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

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

img

webkit内核、Firefox下的特殊情况

  • element自身的display属性为none
<div class="position-outer" style="position: relative;"><div class="position-inner" style="postion: relative;"><div class="not-position"><div class="box" style="display: none;"> <!-- 注意这里! --></div></div></div>
</div>

img

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

img

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

img

打印element.offsetWidth:

img

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

  • 有滚动条情况下

img

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

img

打印box.offsetLeft和box.offsetTop:

img

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

img

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

img

打印box.offsetLeft和box.offsetTop:

img

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

img

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

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

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

我们打印下parent.offsetleft:

img

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

img

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

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

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

element.offsetLeft = element.left + element.marginLeft

评论1:

纠正一下,插入完parent元素后,box的offsetTop值应为114px,因为parent元素并没有margin-top值,而浮动之后的parent.offsetLeft应为89px,它已经包含了parent元素的margin-left值(13px),再看插入parent后,box的offsetLeft为127px(margin-left的值计算在内),将127px-13px+54px( 89px - 35px(position的padding值) )=168px这就为浮动之后的box的offsetLeft的值。
转载自


http://chatgpt.dhexx.cn/article/FLTYjooI.shtml

相关文章

div之各种高度篇-offsetHeight、clientHeight、scrollHeight、 offsetHeight等等

资历尚浅,真的记不住这些花里胡哨的高度宽度、但是又经常要用到,头大 以下都是自己的理解,如果有误可以提醒下谢谢~ 以上图div为例子 一、offsetHeight = height + border + padding = 342 (返回不带px的数值) 二、clientHeight = height + padding = 340 (返回不…

关于offsetTop与offsetHeight的区别以及使用方法

offsetTop和offsetHeight是设置一个元素的位置和获取圆度大小经常会使用的参数&#xff0c;下面具体讲一下他们的区别于联系&#xff1a; 例如obj为html的一个元素对象&#xff0c; obj.offsetTop指的是obj距离上方或者父级元素&#xff08;position非static&#xff09;的位…

clientHeight和offsetHeight

clientHeight&#xff1a;包括padding但不包括border、水平滚动条、margin的元素的高度。对于inline的元素这个属性一直是0&#xff0c;单位px&#xff0c;只读元素。 offsetHeight&#xff1a;包括padding、border、水平滚动条&#xff0c;但不包括margin的元素的高度。对于in…

PHP 简单封装返回JSON数据接口

前言 本文使用 php 来做一个简单的接口&#xff0c;客户端传入数据&#xff0c;该接口返回 JSON 格式数据。 api.php <?php/* * (PHP简单封装JSON数据接口) * param integer $code 状态码 * param string $message 提示信息 * param array $data 数据 * return json(str…

PHP微信支付接口开发

在开始之前先看下功能 然后选择刷卡支付 输入手机微信钱包的授权码&#xff0c;成功运行 方法步骤&#xff1a; 需要先下一个DEMO&#xff0c;下DEMO的地方有两个&#xff1a; 一个是微信官方开发者文档地址 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter11_1…

Shopify 全套接口开发,产品上传、订单检索、自动履行【PHP接口】开发

PHP 接口: 以下接口为基础实现接口,可以自由调用。 以下基础方法实现了: 产品的自动发布,将产品直接发布到店铺中。 订单的自动检索,将店铺中需要履行的订单全部拉下来。 订单的自动履行(发货),将运单号同步到店铺后台发货。 产品上传推荐使用CSV 方式,即将多个产品…

人人都是接口开发大师,这个开源项目花5分钟就可以开发一个API接口

PhalApi开源接口框架 读音&#xff1a;派框架&#xff0c;官网&#xff1a;https://www.phalapi.net/ PhalApi是一个PHP轻量级开源接口框架&#xff0c;致力于快速开发接口服务。支持HTTP/SOAP/RPC等协议&#xff0c;可用于搭建接口/微服务/RESTful接口/Web Services。承诺永…

php API接口入门

1.简述: api接口开发,其实和平时开发逻辑差不多;但是也有略微差异; 平时使用mvc开发网站的思路一般是都 由控制器 去 调用模型,模型返回数据,再由控制器把数据放到视图中,展现给用户; api开发是:使用控制器 去调用模型,模型返回数据,在有控制器 输出 json格式字符…

php开发之接口的使用

继承简化了对象&#xff0c;类的创建&#xff0c;增加了代码的可重性&#xff0c;但php只支持单继承&#xff0c;如果要实现多重继承&#xff0c;就要使用多个接口。 接口通过interface关键字来声明&#xff0c;并且类中只能包含未实现的方法和一些成员变量&#xff0c;格式如…

PHP开发APP接口注意事项

一、双方统一接口开发文档 为了提升开发效率及沟通方便&#xff0c;需要建立规范的开发文档。 一般保护接口的功能或页面、接口地址、接口参数、接口返回值等说明。 参考文档格式&#xff1a; 二、注意以下 分版本&#xff0c;为后面接口升级做好打算。提供密钥和token。…

YII2.0 接口开发步骤

新建表的model来操作表。 访问你本地站点的XXX/gii 即可打开。如果提示无法访问请自行修改config/web.php 文件下面的IP选项 $config[modules][gii] [class > yii\gii\Module,allowedIPs>[127.0.0.1,::1,"192.168.*", "自己定义自己的IP"],]; 这时候…

PHP开发微信商家转账到零钱接口

仔细阅读了微信接口文档并且参考网上的案例&#xff0c;完成了商家转账到零钱的接口开发&#xff0c;目前已在使用中 下面是完整代码&#xff1a; /*** notes 商家转账到零钱*/public static function transfer($withdrawApply,$userAuth,$config){//请求URL$url https://api…

php开发App接口

APP接口简介&#xff1a; 什么是app接口&#xff1f;app接口就是用服务端程序如php写好的脚本&#xff0c;以供app客户端请求而获得数据的一个东西。比如一个视频app的首页&#xff0c;肯定有一些视频列表&#xff0c;那么当你打开这个app时&#xff0c;这个封装在app里的这个首…

PHP对接抖音开发平台接口

一、说明二、代码三、代码运行需知四、功能扩展五、接口调用需要注意的点六、接口文档中的 坑&#xff08;以订单列表接口为例&#xff09;1、请求参数、响应参数 代表的具体值不清晰2、页码从第0页开始&#xff08;这个属于需要注意的点&#xff09;3、金额 是元 还是 分&…

PHP api接口开发

本人第一次使用PHP 开发API 1、第一步 开发框架&#xff1a;http://www.thinkphp.cn/down.html 本人下载 :ThinkPHP5.0.24核心版 需要先登陆 下载解压&#xff0c;放入phpstudy 的 网站根目录下&#xff1a;www文件&#xff0c;如下图&#xff1a; phpstudy 选择Apache&am…

PHP接口加密

在工作中PHP接口开发是PHP常见的技术&#xff0c;通过对接口进行一些操作&#xff0c;可以访问接口获取数据&#xff0c;给app/前端提供数据接口等,如果接口没有加密&#xff0c;很容易发生盗用和不安全的操作.下面介绍一下常见的接口加密方法。 一.使用token进行加密解密&…

php接口开发简单实例

刚刚写成人生第一个服务器接口&#xff0c;总结分享一下经验&#xff0c;没写过接口的可以看下。 这里以用户用id请求自己个人信息业务为例&#xff1a; <?php $id $_POST["user_id"]; if ($id ! 10086){exit(); }$userinfo array(username>jason,password…

如何用PHP编写简单的api数据接口

点击注册直接获取API数据 一、编写接口所需几样工具或软件&#xff08;均是win764位&#xff09; 1.phpStudy、SQLyog和编码工具&#xff08;sublime text/webStorm/vs code均可&#xff0c;按自己习惯来&#xff09;&#xff1b; 2.安装好phpStudy之后&#xff0c;打开软件…

PHP开发APP接口实现--基本篇

最近一段时间一直在做APP接口&#xff0c;总结一下APP接口开发以来的心得&#xff0c;与大家分享&#xff1a; 1. 客户端/服务器接口请求流程&#xff1a; 安卓/IOS客户端 –> PHP接口 –> 服务器端 –> 数据处理 –> 返回值&#xff08;客户端接收并处理&…

PHP服务器端API原理及示例讲解(接口开发)

直接获取API接口数据的方法点击获取 相信大家都做过PHP请求API接口获取数据&#xff0c;比如淘宝API&#xff0c;微信公众平台&#xff0c;天气查询&#xff0c;快递查询等&#xff0c;有的需要参照接口文档根据签名算法构造sign&#xff08;签名&#xff09;&#xff0c;或者设…