关于元素的尺寸和位置,这原本是 CSS 干的事,但更多的时刻须要用 JavaScript 来猎取这些参数,比方一个很好的例子 js 完成的图片瀑布流。
在引见 JS 中的例子之前,先来申明一下 css 中的元素尺寸。
CSS 中的 width 和 height
先开个头吧,一个元素所占有的物理尺寸包含以下几个部份,由内到外分别是内容,padding,border,margin,这些值加到一同才算是一个元素实在尺寸。这内里并没有把转动条的宽度算上,由于转动条时占用 padding 的宽度的,假如 padding 宽度小于转动条,那末转动条多出来的部份将占用内容的宽度。padding与转动条关联。
比方下面的这个例子:
// html
<div class="test"></div>
// css style
.test{
width:100px;
height: 100px;
padding:10px;
border:2px solid black;
margin: 5px;
}
上图是 chrome 调试下的 styles,所以 .test
的现实宽度应该是 100px + 20px + 4px + 10px = 134px,这里把 margin 也算进去,高度的盘算同理。晓得这一点很重要,当我们须要准确设定元素宽度的时刻,就不会由于尺寸过大而把元素挤到下一行。
不过,这是入门级的 CSS。除此以外,还须要晓得一个异常重要的 CSS 款式,即 box-sizing
,可参考 MDN 上的引见。
/* 关键字值 */
box-sizing: content-box;
box-sizing: border-box;
box-sizing
有两个关键字(听说另有一个 padding-box,横竖我在 chrome 上测试不成功),content-box 是默认值,此时 width 只示意内容 content,border-box 示意元素的 width 即是 content + padding + border 三者之和。border-box 异常有效,特别当我们在运用 100% 来划定宽高的时刻,假如元素存在 border 或 padding,将直接致使元素的现实大小大于 100%,预计另有人记得 calc
带来的痛楚。
修正上面的例子:
.test{
width:100px;
height: 100px;
padding:10px;
border:2px solid black;
margin: 5px;
box-sizing: border-box;
}
76 + 20 + 4 = 100px
,此时的 width 示意三者之和,而内容的宽度只要 76px 了。
JS 猎取元素尺寸
万万不要尝试用 element.style.width 或 element.style.height 来取得元素的高度和宽度,它们的默认值都是 0,除非你在 html 元素内里设置,不然 js 是没法取得 css 的款式的,必需要用其他的要领。比方下面这段代码 element.style.width
的值才是 100px:
<div class="test" style="width:100px"></div>
JS 中 element 对象供应 offsetHeight
, scrollHeight
, clientHeight
(每一个都对应 width),个中:
offsetHeight 能够用来盘算元素的物理空间,此空间包含内容,padding 和 border(还包含转动条的宽度,但大多时刻转动条的宽度是盘算到 padding 和内容中的)。
var test = document.getElementsByClassName('test')[0];
test.offsetHeight // 100
scrollHeight 用来盘算可转动容器的大小,包含不可见的部份,比方一个 300*300 的容器放入一个 600*600 的图片,此时 scrollHeight 为 600,固然,scrollHeight 的值须要加上 padding 的值。
clientHeight 示意可视地区,包含内容和 padding ,假如有转动条,还须要减去转动条的宽度。
举个例子,照样之前谁人 test,到场 test2:
<div class="test">
<div class="test2"></div>
</div>
//css
.test{
overflow: auto; //新增
}
.test2{
width: 150px;
height: 150px;
background-color: gray;
}
来看一看 test 的输出值是多少:
var test = document.getElementsByClassName('test')[0];
test.offsetHeight // 100
test.scrollHeight // 170
test.clientHeight // 79
此时转动条的宽度是 17px,依据前面的引见,转动条时占用 padding 和 content 宽度的,而 17px 大于 padding 的 10px,故另有 7px 会占有 content。
剖析一下,offsetHeight 的值是 100,padding 10px,转动条虽然存在,然则占了 padding 和内容的空间,offsetHeight 的值是 4+20+76 = 100px。scrollHeight 的值是可转动的局限加上padding 值,一样不包含转动条,即 150+20 = 170px。clientHeight 的值是可见地区,然则不包含转动条的值(转动条。。。),所以20+76-17 = 79px。
实在也不是异常复杂。这个时刻能够得出转动条宽度的盘算:offsetHeight 减去 border 和 clientHeight 的和就是转动条宽度。
猎取元素内容的尺寸
刚说了半天,照样没法取得元素内容的尺寸,最接近内容宽度的是 clientHeight,在没有转动条的情况下,减去 padding 值就是内容的尺寸。
怎样猎取元素的实在尺寸呢?
经由过程 getComputedStyle (IE 下 currentStyle),MDN 引见。
getComputedStyle 这个函数重要供应给我们元素 border 和 padding 宽度在内的一系列值(依然不要妄图经由过程 element.style.border-width 取得),加上本来的 offsetHeight,就能够减去 border 和 padding 的值取得元素的实在尺寸。
// 斟酌 IE 的兼容性
function getStyle(el) {
if(window.getComputedStyle) {
return window.getComputedStyle(el, null);
}else{
return el.currentStyle;
}
}
function getWH(el, name) {
var val = name === "width" ? el.offsetWidth : el.offsetHeight,
which = name === "width" ? ['Left', 'Right'] : ['Top', 'Bottom'];
// display is none
if(val === 0) {
return 0;
}
var style = getStyle(el);
// 摆布或高低双方的都减去
for(var i = 0, a; a = which[i++];) {
val -= parseFloat( style["border" + a + "Width"]) || 0;
val -= parseFloat( style["padding" + a ] ) || 0;
}
return val;
}
// 测试,准确
getWH(test, 'width'); // 76
猎取元素的位置
在这里先隆重推出一个重量级佳宾函数,即 getBoundingClientRect
,贴上 MDN 链接。
element.getBoundingClientRect()
会返回一个数组,比方:
test.getBoundingClientRect();
bottom:108
height:100
left:13
right:113
top:8
width:100
个中,width 和 height 跟 element.offset 的值是一致的,left bottom 等值则示意间隔浏览器窗口的间隔,假如要取得元素的位置,只须要获得 left 和 top 的值即可,
var X= test.getBoundingClientRect().left;
var Y =test.getBoundingClientRect().top;
//再加上转动间隔,就能够获得相对位置
var X= test.getBoundingClientRect().left+document.body.scrollLeft;
var Y =test.getBoundingClientRect().top+document.body.scrollTop;
此要领以外,另有其他要领。比方每一个元素都有 offsetTop 和 offsetLeft 属性,示意间隔父容器左、上角的边距,offsetParent 示意父容器,先获得间隔父容器的间隔,顺次累加,获得相对位置。
function getPosition(element, name){
name = name.toLowerCase().replace("left", "Left").replace("top", "Top");
var offset = 'offset' + name;
var actualLeft = element[offset];
var current = element.offsetParent;
while (current !== null){
actualLeft += current[offset];
current = current.offsetParent;
}
return actualLeft;
}
getPosition(test,'left') // 13
getPosition(test,'top') // 8
效果和 getBoundingClientRect() 值一样,有时刻须要斟酌是相对于屏幕的位置照样相对位置,然后再做进一步的盘算。
总结
觉得近来的文章愈来愈水,重要是由于近来都在抓基础,进修 nodejs 和 ES6 的基础语法,没时间去看一下比较盛行的框架。白昼又特别忙,学校里又一大堆事变,种种焦躁。共勉!
参考
用Javascript猎取页面元素的位置
关于元素的尺寸(dimensions) 申明
height、clientHeight、scrollHeight、offsetHeight区分
欢迎来我博客交换。