原生js如何获取宽高

it2023-10-10  71

foreword(前言)

最近项目中需要获取 dom 元素的尺寸,所以借此对比分析一下 js 所有获取尺寸的方法,以及相关的 dom 定位方式。

JS 尺寸、定位都有哪些获取方式呢

JS 尺寸获取方法:

clientWidth & clientHeightoffsetWidth & offsetHeightscrollWidth & scrollHeightgetComputedStylegetBoundingClientRect

clientWidth & clientHeight

The Element.clientWidth property is zero for inline elements and elements with no CSS; otherwise, it’s the inner width of an element in pixels. It includes padding but excludes borders, margins, and vertical scrollbars (if present).

clientWidth 包括 content、padding 两个部分,而不包括 border、margin,以及滚动条的宽度。

offsetWidth & offsetHeight

Typically, offsetWidth is a measurement in pixels of the element’s CSS width, including any borders, padding, and vertical scrollbars (if rendered). It does not include the width of pseudo-elements such as ::before or ::after.

offsetWidth 包括 content、padding、滚动条、border。

scrollWidth & scrollHeight

The scrollWidth value is equal to the minimum width the element would require in order to fit all the content in the viewport without using a horizontal scrollbar. The width is measured in the same way as clientWidth: it includes the element’s padding, but not its border, margin or vertical scrollbar (if present). It can also include the width of pseudo-elements such as ::before or ::after. If the element’s content can fit without a need for horizontal scrollbar, its scrollWidth is equal to clientWidth.

scrollWidth 在没有横向滚动条的时候,大小跟 clientWidth 一样;而如果有横向滚动条,则是可视区域 + 隐藏区域 + padding。

以下是一段测试代码:

<!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> #box { width: 100px; height: 100px; padding: 10px; background: red; overflow: auto; } </style> </head> <body> <div id="box"> hkjhjkhhkjhkjhjkhjkhjkhhkhkjhjkhjkhkjhkjhkjhjkhjk jkjkljljkl hkjhjkhjk hkjhjkh hkjhjkh hkjhjkh hkjhjkh hkjhjkh hkjhjkh hkjhjkh hkjhjkh hkjhjkh </div> <script> var box = document.getElementById('box') // client console.log('clientWidth:', box.clientWidth) console.log('clientHeight:', box.clientHeight) // offset console.log('offsetWidth:', box.offsetWidth) console.log('offsetHeight:', box.offsetHeight) // sroll console.log('scrollWidth:', box.scrollWidth) console.log('scrollHeight:', box.scrollHeight) </script> </body> </html>

注:clientXXX & offsetXXX & scrollXXX 获取的数据均为 round 四舍五入取整过,如果想要精确的数值,则可以通过 element.getBoundingClientRect() 进行获取。

getComputedStyle

The Window.getComputedStyle() method returns an object containing the values of all CSS properties of an element, after applying active stylesheets and resolving any basic computation those values may contain. Individual CSS property values are accessed through APIs provided by the object, or by indexing with CSS property names.

Window.getComputedStyle 方法返回一个对象,可以通过属性名或者它提供的 api 方法获取某个 css 属性的值。

语法:

var style = window.getComputedStyle(element [, pseudoElt]);

参数:

element: 我们想要获取样式的 dom 元素对象;pseudoElt: 伪元素选择器;

大致意思就是,如果只传第一个参数,则获取的是第一个参数 element 的样式集合对象,而如果传了两个参数,则是获取 element 中匹配 pseudoElt 伪元素选择器的伪元素的样式集合对象。

注,以下情况下,浏览器会抛 TypeError 的异常:

element 不是一个 element 类型的 dom 元素对象;pseudoElt 不是一个有效的伪元素选择器,这里说的有效性是指语法有效性,比如:“::unsupported” 这个选择器虽然不存在,但是它语法是有效的,所以不会被抛异常;

以下是一段测试代码:

<!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> #box { width: 100px; height: 100px; padding: 10px; background: red; overflow: auto; } #box::before { content: ''; width: 55px; height: 55px; line-height: 55px; display: block; background: yellow; } #box::after { content: ''; width: 55px; height: 55px; display: block; background: green; } </style> </head> <body> <div id="box"></div> <script> var box = document.getElementById('box') var computedStyleObj = window.getComputedStyle(box, '::before') console.log('computedStyleObj-lineHeight:', computedStyleObj.lineHeight) // 55px console.log('computedStyleObj-lineHeight:', computedStyleObj.getPropertyValue('line-height')) // 55px </script> </body> </html>

window.getComputedStyle 返回的对象其实和 element.style 返回的对象属于同一种类型—— CSSStyleDeclaration,但是两者还是有区别的:

window.getComputedStyle 返回的对象是只读的,并不能设置样式;element.style 返回的对象可读写,可以直接通过 element.style[Css Attribute Name] 的形式在行内样式上设置样式;

在许多在线的演示代码中,getComputedStyle 是通过 document.defaultView 对象来调用的。大部分情况下,这是不需要的,因为可以直接通过 window 对象调用。但有一种情况,你必需要使用 defaultView, 那是在firefox3.6 上访问子框架内的样式 。

注:

返回的 CSSStyleDeclaration 对象将包含所有受支持的CSS属性长名称的活动值,如:border-bottom-width;获取属性值有两种方法,api 或者索引,比如:window.getComputedStyle(element).getPropertyValue(‘border-bottom-width’)、window.getComputedStyle(element).borderBottomWidth、window.getComputedStyle(element)[‘border-bottom-width’]、window.getComputedStyle(element)[‘borderBottomWidth’];

getComputedStyle的返回值是 resolved values, 通常跟CSS2.1中的computed values是相同的值。 但对于一些旧的属性,比如width, height, padding 它们的值又为 used values。最初, CSS2.0定义的计算值Computed values 就是属性的最终值。 但是CSS2.1 重新定义了 computed values 为布局前的值, used values布局后的值。 布局前与布局后的区别是, width 或者 height的百分比可以代表元素的宽度,在布局后会被像素值替换。

大致意思就是返回的值是计算过的值,比如:某些百分比的值会被计算,然后转换为 px 的值;

在某些情况下,通过浏览器会特意返回不准确的值。 特别是在避免CSS 浏览历史泄露的安全问题, 比如,浏览者看过某个网站,它的链接通常会变成蓝色带下划线的链接,通过判断链接的颜色(getComputedSytle(node, null).color) 是否为蓝色,就会泄露用户的浏览历史,所以浏览器会特意返回不准确的值,保护用户隐私。可以了解更多关于css安全的链接http://blog.mozilla.com/security/2010/03/31/plugging-the-css-history-leak/ 和http://hacks.mozilla.org/2010/03/privacy-related-changes-coming-to-css-vistited/

返回的某些属性值是带有 px 的字符串,而不是简单的数值。

getBoundingClientRect

The Element.getBoundingClientRect() method returns the size of an element and its position relative to the viewport. The element’s size is equal to its width/height + padding + border-width in the case that the standard box model is being used, or width/height only if box-sizing: border-box has been set on it.

element.getBoundingClientRect() 返回的一个对象,这个对象包含了 element 的尺寸(标准盒子模型下的尺寸)和相对于窗口的定位。

以下为测试代码:

<!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> div { width: 400px; height: 200px; padding: 20px; margin: 50px auto; background: purple; } </style> </head> <body> <div> </div> <script> let elem = document.querySelector('div'); function getInfo() { let elem = document.querySelector('div'); let rect = elem.getBoundingClientRect(); for (var key in rect) { if (typeof rect[key] !== 'function') { let para = document.createElement('p'); para.textContent = `${ key } : ${ rect[key] }`; console.log(para); } } console.log('\n') } window.onscroll = getInfo </script> </body> </html>

浏览器兼容性

详见以下文章末尾:

clientWidth & clientHeight:https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidthoffsetWidth & offsetHeight:https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidthscrollWidth & scrollHeight:https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidthgetComputedStyle:https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStylegetBoundingClientRect:https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

参考文章

clientWidth & clientHeight:https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidthoffsetWidth & offsetHeight:https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidthscrollWidth & scrollHeight:https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidthgetComputedStyle:https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStylegetBoundingClientRect:https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

last(最后) 非常感谢您能阅读完这篇文章,您的阅读是我不断前进的动力。

对于上面所述,有什么新的观点或发现有什么错误,希望您能指出。

最后,附上个人常逛的社交平台: 知乎:https://www.zhihu.com/people/bi-an-yao-91/activities csdn:https://blog.csdn.net/YaoDeBiAn github: https://github.com/yaodebian

个人目前能力有限,并没有自主构建一个社区的能力,如有任何问题或想法与我沟通,请通过上述某个平台联系我,谢谢!!!

最新回复(0)