前言
这段时间在研究一个反爬产品,环境检测用到了很多个盒子宽高取值方法,如window.outerWidth
、window.screen.availWidth
,各个方法取值结果不大相同,在此记录下遇到的方法。
各宽方法区别
这里就讲解下各宽度方法的区别,同样可以使用与高度方法的理解
宽度方法:outerWidth
、width
、innerWidth
、offsetWidth
、scrollWidth
、clientWidth
、availWidth
以盒子取值区别
一般来说盒子会有width
、offsetWidth
、scrollWidth
、clientWidth
这四个宽取值方法
width
- 定义:CSS属性,用于设置元素的宽度。
- 取值:取决于CSS样式中的设置,可以是像素值(px)、百分比(%)、视口单位(vw)、em、rem等。
- 特点:这是元素宽度的“设定值”,实际渲染时可能受其他CSS属性(如padding、border、margin)影响。
offsetWidth
- 定义:JavaScript属性,表示元素的布局宽度,即元素在页面上占用的宽度。
- 取值:等于元素的CSS宽度加上左右内边距(padding)和左右边框(border)的宽度(如果存在滚动条且可见,则也包含滚动条的宽度)。
- 特点:这是一个“实际占用宽度”的值,包括了元素内容区、内边距和边框的宽度。
scrollWidth
- 定义:JavaScript属性,表示元素内容的总宽度。
- 取值:如果元素内容没有溢出,则scrollWidth等于clientWidth或offsetWidth(取决于是否有边框和内边距);如果内容溢出,则scrollWidth等于内容实际占用的宽度。
- 特点:这个值用于确定元素内容的总宽度,即使部分内容不可见(因为溢出)。
clientWidth
- 定义:JavaScript属性,表示元素内容区加上左右内边距的宽度。
- 取值:等于元素的CSS内容宽度加上左右内边距的宽度(不包括边框和滚动条的宽度)。
- 特点:这个值反映了元素可见内容的宽度,不考虑边框和滚动条。
具象展示
如下图,我们设置了一个width=56的按钮,其边框(border)=3、内边距(padding)=6和外边距(margin)=5,那么它的各宽方法取值结果如下
width:56
offsetWidth:74(width + padding(6*2)+ border(3*2))
scrollWidth:68(width + padding(6*2))
clientWidth:68(width + padding(6*2))
一般取值结果大小关系
在大多数情况下(不考虑滚动条和边框对内边距和内容区的影响,且内容没有溢出):
- offsetWidth ≥ clientWidth:因为offsetWidth包括了边框的宽度(如果有的话),而clientWidth不包括。
- scrollWidth = offsetWidth(或clientWidth,取决于是否有边框和内边距导致的内容溢出):在没有内容溢出的情况下,scrollWidth等于元素的布局宽度或可见内容宽度。
- width(CSS设定值)与offsetWidth、clientWidth的关系取决于具体的CSS样式和元素布局。如果CSS样式中只设置了width,没有padding和border,那么width可能等于clientWidth(但不等于offsetWidth,因为offsetWidth还包括了边框)。如果设置了padding和border,则这些值之间会有差异。
需要注意的是,当元素内容溢出时,scrollWidth的值会大于clientWidth和offsetWidth(如果滚动条可见且包含在offsetWidth中,则可能等于offsetWidth)。此外,不同浏览器对边框、内边距和滚动条的处理可能有所不同,因此在实际开发中需要注意这些差异。
以屏幕取值区别
这种取值在反爬检测中比较常见,下面列出我遇到的检测点进行讲解:
window.screen.availWidth
,window.screen.availHeight
window.screen.width
,window.screen.availHeight
window.innerWidth
,window.innerHeight
document.body.clientWidth
,document.body.clientHeight
window.outerWidth
,window.outerHeight
window.screen.width
- 取值方式:这个属性返回用户屏幕的整个宽度(以像素为单位),包括所有系统级元素,如任务栏、窗口边框等。
- 结果大小:通常大于或等于
window.screen.availWidth
,因为它包括了屏幕上的所有区域。
window.screen.availWidth
- 取值方式:这个属性返回用户屏幕的可用宽度(以像素为单位),即屏幕宽度减去系统级元素(如任务栏、窗口边框)所占用的空间。
- 结果大小:通常小于或等于
window.screen.width
,因为availWidth
考虑了屏幕上的不可用区域。
window.innerWidth
- 取值方式:这个属性返回浏览器视口(viewport)的内部宽度(以像素为单位),即浏览器窗口的可见内容区域宽度,不包括浏览器的边框、滚动条、书签栏等。
- 结果大小:可能小于
window.screen.availWidth
(因为浏览器窗口可能不是全屏的,或者因为存在浏览器边框、书签栏等),并且可能大于或小于document.body.clientWidth
(取决于页面的布局和滚动情况)。
window.outerWidth
- 取值方式:这个属性返回整个浏览器窗口的宽度(以像素为单位),包括窗口的边框、标题栏、滚动条等所有组成部分。
- 结果大小:通常大于
window.innerWidth
,因为它包括了浏览器窗口的所有外部元素。
document.body.clientWidth
- 取值方式:这个属性返回HTML文档主体(body)的宽度(以像素为单位),即文档内容区域的宽度,不包括滚动条的宽度(如果存在的话)。注意,这个值可能会受到CSS样式(如边距、填充、边框等)的影响。
- 结果大小:可能小于或等于
window.innerWidth
(因为页面内容可能设置了边距、填充或因为内容宽度本身小于视口宽度),也可能大于window.innerWidth
(如果页面内容超出了视口并产生了水平滚动条,但滚动条本身不计入clientWidth
)。
具象展示
我的屏幕大小宽度是2560,下图是在开发者工具不影响宽度时它们的取值结果
当把开发者工具置于向右时它们的取值结果
当把开发者工具置于向下同时缩小浏览器窗口时它们的取值结果
通过上面的对比可以知道,一般情况下window.screen.width
和window.screen.availWidth
跟屏幕的大小有关,不会受到浏览器界面状态影响;而window.outerWidth
、window.innerWidth
和document.body.clientWidth
则跟浏览器界面大小有关, 会受到浏览器界面状态影响。而这个值差就很容易被检测到,毕竟调试时一般会影响浏览器界面状态。
一般取值结果大小关系
window.screen.width
>=window.screen.availWidth
(屏幕的整个宽度通常大于或等于可用宽度)window.outerWidth
>=window.innerWidth
(浏览器窗口的外部宽度通常大于或等于内部宽度)window.screen.availWidth
与window.innerWidth
之间没有固定的关系,因为浏览器窗口可能不是全屏的,也可能受到操作系统设置、浏览器布局等因素的影响。window.innerWidth
与document.body.clientWidth
之间也没有固定的关系,因为页面的布局和CSS样式会影响document.body.clientWidth
的值。