• 先区分一下 window 对象和 document 对象:
    window 对象表示浏览器中打开的窗口,而 document 对象表示整个 html 文档,它是 window 对象的一部分。

原生 JavaScript

1.与 window 相关的宽高

1.1 与窗口相关

window.innerHeight/window.innerWidth:
返回表示窗口的内部高度/宽度的数字。不包括开发者工具、顶部栏、侧边栏、滚动条、边框等不由 HTML 控制的部分

window.outerHeight/window.outerWidth
返回表示窗口的外部高度/宽度的数字。包括开发者工具、顶部栏、侧边栏、滚动条、边框等不由 HTML 控制的部分

1.2 与屏幕相关

window.screen.width/window.screen.height
返回表示屏幕的宽度/高度的数字。包括可能位于任意一侧的任务栏。这两个属性不受浏览器窗口位置的影响。

window.screen.availHeight/window.screen.availWidth
返回表示屏幕的可用宽度/可用高度的数字。不包括可能位于任意一侧的任务栏。这两个属性不受浏览器窗口位置的影响

window.screenLeft/window.screenTop:
返回表示窗口到屏幕距离的数字。无视任务栏。注意:IE 和 Opera 下表示的是窗口文档区到屏幕的距离,这意味着窗口最大化时,screenTop 返回的是窗口顶部栏的高度而不是 0。

兼容性:主流浏览器均支持,FireFox 浏览器在 v64 之后才支持

window.screenY/window.screenX:
返回表示窗口到屏幕距离的数字。
兼容性:主流浏览器均支持

2.与 document 相关的宽高

2.1 client 系列

element.clientHeight/element.clientWidth
返回元素的可视部分的高度/宽度,且不包括滚动条。即
clientHeight = height + padding - scrollBar
clientWidth = width + padding - scrollBar

element.clientTop/element.clientLeft
返回元素的上边框/左边框厚度。即
clientTop = borderTop
clientLeft = borderLeft

2.2 offset 系列

element.offsetWidth/element.offsetHeight
返回元素的总高度/总宽度,包括滚动条和边框。即
offsetWidth = width + padding + border
offsetHeight = height + padding + border

其实这里可以看出来,以 offsetWidth 为例,可以得出:offsetWidth = clientWidth + scrollBar + border

element.offsetTop/element.offsetLeft
首先了解什么是 offsetParent: 它是距离 element 最近的设置了定位的父元素,如果 element 的所有父元素都没有设置定位,则 offsetParentbody 元素。

element.offsetTop = offsetParent.marginTop + offsetParent.borderTop + offsetParent.paddingTop + element.marginTop

element.offsetLeft = offsetParent.marginLeft + offsetParent.borderLeft + offsetParent.paddingLeft + element.marginLeft

2.3 scroll 系列

scrollWidth/scrollHeight

对于 body 元素,在没有滚动条的情况下:
body.scrollWidth = window.innerWidth - scrollBar
body.scrollHeight = window.innerHeight - scrollBar
在有滚动条的情况下:
body.scrollWidth = width + padding + border + margin
body.scrollHeight = height + padding + border + margin

对于其他元素,在没有滚动条的情况下:
element.scrollWidth = element.clientWidth
element.scrollHeight = element.clientHeight
在有滚动条的情况下跟 body 元素是一样的。

element.scrollTop/element.scrollLeft
返回元素在垂直方向或者水平方向上已滚动的距离。

例如,下图中的红框是固定的屏幕可视区,而网页视为可以上下拖动的文档,当滚动条下拉的时候,实际上是文档向上拖动,而这个拖动的距离就是 element.scrollTop

2.4 返回对象系列

element.style.property/element.getBoundingClientRect().property;

对于一个 dom 元素,它的 style 属性返回的是一个属性可读写的对象,且属性值常常是带有单位的。注意:这种方式只能够获取元素的行内样式,而并不能获取到元素的最终样式 —— 要获取计算好的样式,使用 element.currentstyle(IE 浏览器)或者 element.getComputedStyle(IE 之外的浏览器)。

对于一个 dom 元素,它的 getBoundingClientRect() 方法返回的是该元素对应的矩形对象,通过 topbottomleftright 可以分别获得该对象各边相对于窗口上边或者左边的距离。

3.与 event 相关的宽高

event 对象同样存在着很多位置属性,这些位置属性的参照物都不同。

ev.clientX/ev.clientY

事件发生时,鼠标点击位置相对于浏览器可视区(不包括滚动条和工具栏)左上角(该点为原点)的坐标。

ev.screenX/ev.screenY

事件发生时,鼠标点击位置相对于设备屏幕左上角(该点为原点)的坐标

ev.offsetX/ev.offsetY

事件发生时,鼠标点击位置相对于事件源左上角(该点为原点)的坐标。FireFox 不支持

ev.layerX/ev.layerY

事件发生时,鼠标点击位置相对于 document 或者设置了定位的事件源左上角(该点为原点)的坐标。仅 FireFox 支持,要想使 layerXoffsetX 相等,必须给事件源设置定位。

ev.pageX/ev.pageY

事件发生时,鼠标点击位置相对于页面左上角(该点为原点)的坐标。窗口无滚动条时,该属性与 ev.clientX/ev.clientY 等价;窗口出现滚动条时,该属性的值将更大,因为它针对的是整个页面,即包含已滚动的区域。

jQuery

width()/height()
无参时返回元素的 content 的宽度/高度,传参时(数字或者函数)设置元素的 content 的宽度/高度。对于 window.document 传参无效,即只支持读不支持写

innerWidth()/innerHeight()
基本同上,不同的是额外包含了元素的 padding,另外不推荐对 window.document 使用这个方法。

outerWidth()/outerHeight()
基本同上,不同的是额外包含了元素的 border,如果传参 true,则还会包含 margin。同样不推荐对 window.document 使用这个方法。

scrollLeft()/scrollTop()
水平方向上或者垂直方向上,滑块相对于整个滚动条的位置。对于某个元素,滑块处于初始位置或者无滚动条时,该方法返回 0。

offset()

返回元素相对于 document (左上角为原点)的当前坐标值,因此即使页面向上拖动,坐标值也不变。

position():

返回元素相对于其 offsetParent((左上角为原点)) 的当前坐标值

两者区别看下图:

参考:
https://juejin.im/entry/583a9d4961ff4b007ecbfaff
https://segmentfault.com/a/1190000007515034
https://www.jianshu.com/p/60332df38393