關於元素的尺寸和位置,這本來是 CSS 乾的事,但更多的時候須要用 JavaScript 來獲取這些參數,好比一個很好的例子 js 實現的圖片瀑布流。javascript
在介紹 JS 中的例子以前,先來講明一下 css 中的元素尺寸。css
先開個頭吧,一個元素所佔據的物理尺寸包括如下幾個部分,由內到外分別是內容,padding,border,margin,這些值加到一塊兒纔算是一個元素真實尺寸。這裏面並無把滾動條的寬度算上,由於滾動條時佔用 padding 的寬度的,若是 padding 寬度小於滾動條,那麼滾動條多出來的部分將佔用內容的寬度。padding與滾動條關係。html
好比下面的這個例子:java
// 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 也算進去,高度的計算同理。知道這一點很重要,當咱們須要精確設定元素寬度的時候,就不會由於尺寸過大而把元素擠到下一行。node
不過,這是入門級的 CSS。除此以外,還須要知道一個很是重要的 CSS 樣式,即 box-sizing
,可參考 MDN 上的介紹。chrome
/* 關鍵字值 */ 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 了。框架
千萬不要嘗試用 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區別
歡迎來我博客交流。