瀏覽器元素尺寸與位置查詢指南

前言

這篇文章主要介紹了有關瀏覽器中獲取座標以及尺寸的幾種途徑,算是比較全的一篇文章了.css

在瀏覽器中獲取元素的座標以及尺寸是很是容易的,有很是多種方式來完成這些需求,可是雜亂的API和不少兼容處理致使了瀏覽器中沒有直接的方式來獲取咱們想要的結果.html

仔細想一想這個問題,爲何瀏覽器並無直接提供一個簡單的屬性就告訴你瀏覽器窗口的大小,或者一個元素的寬高.web

就拿div元素來舉例,咱們有不少的問題影響到了元素寬高:chrome

  • border 是否歸入寬高的計算?
  • padding 是否歸入寬高的計算?
  • magin 是否歸入寬高的計算?
  • box-sizing:border-box; 時候該如何計算?
  • 父元素使用了overflow:hidden;把咱們的元素裁剪了,這時候的寬高該如何計算?
  • 元素使用了overflow出現了滾動條此時該如何計算?

而若是要獲取一個瀏覽器窗口的大小,你還要面對咱們究竟是要獲取哪一個大小?segmentfault

  • 屏幕大小?
  • 瀏覽窗口大小?
  • 瀏覽區域大小?
  • 是否包含滾動條?

固然最終你還要面臨一個兼容問題,致咱們敬愛的IE瀏覽器,不過本文可不探討瀏覽器之間的差別.不過本文的涉及到的內容應該在IE9以上都是能夠正常使用的(不過建議你仍是查下can i use 或者MDN).windows

瀏覽器部分

瀏覽器的寬高計算主要經過window對象來完成.api

這個對象上提供了幾個關鍵屬性:數組

  • window.innerWidth
  • window.innerHeight
  • window.outerWidth
  • window.outerHeight

用人類語言來描述這幾個屬性就是.瀏覽器

屬性名稱 人類解釋
innerWidth 獲取頁面可視區域的寬度包括右側的滾動條(若是有的話).所謂的可視區域就是HTML頁面的內容區域不包括瀏覽器自身的ui所佔用的空間(地址欄和菜單欄等).
innerHeight 獲取頁面可視區域的高度包括底部的滾動條(若是有的話).解釋同上.
outerWidth 獲取瀏覽器窗口寬度.
outerHeight 獲取瀏覽器窗口高度.

友情出演windows畫圖:ui

圖片描述

注意:單位均爲px.

注意:滾動條並不視爲瀏覽器的ui中的內容,而是視爲內容區域的一部分,右側默認的滾動條的寬度包含在window.innerWidth中,可是不屬於html元素和html下的任何元素.

元素部分

屬性

屬性名稱 人類解釋
element.clientWidth 元素內容區域寬度+padding的寬度,若是寬度溢出且裁剪那麼不包含被裁剪掉的部分.
element.scrollWidth 元素實際大小包括父元素出現滾動條後未被展現的部分,計算範圍爲padding+content和clientWidth一致
element.offsetWidth 至關於計算邊框寬度的clientWidth,寬度計算爲content+padding+border.
element.clientHeight 元素內容區域高度+padding的高度,若是高度溢出且裁剪那麼不包含被裁剪掉的部分.
element.scrollHeight 當子元素高度溢出,這裏提供的是子元素的高度包括溢出的部分,大小計算和clientHeight同樣.
element.offsetHeight 至關於計算邊框高度的clientHeight,高度計算爲content+padding+border.
element.clientLeft 元素左邊框的寬度
element.scrollLeft 計算較爲複雜,看後續詳解
element.offsetLeft 計算比較複雜,看下面詳解
element.clientTop 元素上邊框的寬度
element.scrollTop 計算較爲複雜,看後續詳解
element.offsetTop 計算比較複雜,看下面詳解

滾動條的規律

不管是橫向滾動條仍是縱向滾動條,對於測量clientXXX這個單位來講是不包括滾動條的寬(高)的.

例如在下面這張圖中咱們進行測量父元素(黑色區域)的clientWidth結果和子元素(紅色區域)的clientWidth的大小是同樣的.

不過須要注意的是,一旦出現了滾動條對於clientWidth來講就意味着寬度減少(高度同理).

圖片描述

注意:圖片所指的寬度是clientWidth

API名稱 是否包含滾動條大小
offsetXXX 包含
clientXXX 不包含
scrollXXX 不包含

因此在margin:0;padding:0;border-width:0;狀況下offsetWidth - clientWidth=滾動條的寬度.

經過這種方式我求出了chrome瀏覽器滾動條大小是17px整,可是不要忘記這些API只會返回整數.

注意:scrollXXX對於滾動條計算的規則和clientXXX表現一致.

含有box-sizing:border-box的計算

請記住,對於clientXXX來講,元素的大小就是padding+content.

而使用border-box後元素的表現就是padding和border的修改就不會影響到元素的大小.

此時width是多少clientWidth就是多少,height同理.

可是不要忘記了邊框不參與clientXXX的計算,因此border的修改並不會影響元素的寬高變化,那麼那麼當border變大,對應的clientXXX就變小.

一個元素設置了border-box:

box{
  width:100px;
  padding:20px;
  border:20px solid;
  box-sizing:border-box;
}

此時clientWidth= 100px - 20px*2(左右邊框的寬度) = 60px

因爲offsetXXX的計算是包含border的大小的,因此若是一個元素設置了border-box那麼offsetWidth就等於元素的width大小,由於border被限制到了width中.

offsetTopoffsetLeft

子元素的offsetWidth|height是相對於父元素內容區域(padding+content)左側和頂部的偏移量.

這個兩個是相對值,是要求出向對於父級使用定位狀況下來進行計算的,這個父元素能夠經過HTMLElement.offsetParent來獲取到.

例如:父級使用absolute或者relative.

注意:後文提出的父元素都指的是使用了相對定位的父元素.

注意:以上都是對於塊級元素所描述的,對於行內元素或者td等元素相對的父元素不盡相同,這裏不考慮這些狀況,詳情能夠查看上方的連接.

狀況1

圖片描述

在子元素使用了絕對定位的狀況下,父元素沒法干預子元素,因此子元素的scrollLeft就是left+margin-left.

狀況2

圖片描述

第二種狀況就是父元素和子元素都使用了相對定位,而相對定位是不脫離文檔流的,那麼父元素的padding-left就會影響到子元素的scrollLeft屬性.

在線實例

注意:貌似offsetTopLeft在不一樣瀏覽器下有不一樣計算值,會帶來兼容性問題,這裏就不展開了,有興趣的讀者能夠去查閱相關資料.

scrollTopscrollLeft

首先scrollTop和scrollLeft是一對可讀寫的屬性,這意味着你能夠獲取他的值也能夠設置它從而控制滾動的距離.

圖片描述

注意:scrollTop|scrollLeft是用在含有滾動區域的元素上(圖中黑色邊框的元素),而不是被滾動的元素上測量,被滾動的元素scrollTop永遠是0.

簡單理解:在垂直方向上含有滾動條的元素的內容區域的頂部(padding+content)相對於自身頂部邊框的底部向上移動的距離(水平方向同理).

就是scrollTop的大小(圖中超出去的部分).

元素方法

getBoundingClientRect

關於這個方法建議閱讀MDN的指南.固然你也能夠選擇聽我瞎扯幾句.

這個api是ie首先提出(早在ie4時候就有了)的這也是ie對web開發的貢獻之一.

調用這個api會返回一個DOMRect對象,這個對象屢次易名,不過沒有變化過基本概念.

當你調用這個方法的時候他會返回一個對象,該對象擁有以下幾個屬性:

  • left
  • top
  • right
  • bottom
  • width
  • height
  • x
  • y

注意:ie9+包括edge兼容width和height截止到2019年4月5日ie和edge不兼容x和y.

和屬性返回的值有兩點不一樣:

  • 返回的值都是相對值,相對於瀏覽器視口的左上角
  • 返回的值包含小數部分,這意味着獲取到的值更加精確

如何理解:

若是頁面中只有一個1000px高100%寬的div(沒有margin,padding,border),那它的bottom和height應該1000,left和top是0,right和width是元素寬度:

  • 由於咱們指定了1000px因此他的height是1000,
    由於頁面中只有這一個元素,他的內容區域底部到可視區域頂部的距離就是1000,因此bottom是1000.
  • 由於頁面中只有這一個元素,因此這個元素是貼着可視區域的頂端和左側的,因此left和top這兩個值都是0.
  • div默認會鋪滿橫向的空間,橫向空間中只有咱們的div因此right到視口區域左側的距離就是元素的寬度,也是當前可視區域的寬度.

注意:left,right,top,bottom指的是內容區域的邊緣到視口左上角的距離,不包括border和margin,padding,若是指定了box-sizing:border-box;則也包括border和padding.

可是,因爲是該對象的值是相對值,而視口是會移動的,因此top和left的值在視口移動後會發生改變.

圖解:

圖片描述

注意:該屬性返回的值也將滾動條視爲寬度(縱向)和高度(橫向)的一部分.

和getBoundingClientRect相似的還有另一個api叫作getClientRects.這個api做用起來稍微複雜一些,簡單的做用於內聯元素的時候二者有區別,首先它返回的是數組,包含這個內聯元素全部行的DOMRect對象,當內聯元素只有一行的時候這兩個api表現同樣的.

思否上一篇關於 getClientRects的討論

https://segmentfault.com/q/10...

屏幕部分

這部分主要利用window.screen對象,這個對象抽象的表示當前使用的物理顯示設備.

沒錯這個屬性是和硬件有關的,通常的Web開發中不多會使用這個屬性.

經過這個對象你能夠獲取到有關屏幕的分辨率等信息

這裏就很少介紹了,附上一篇介紹詳細的文章:

https://www.cnblogs.com/ndos/...

此外在windows上還有幾個關於屏幕的屬性:

名稱 描述
screenLeft 瀏覽器窗口左側到屏幕左邊緣的距離
screenTop 瀏覽器窗口頂部到屏幕上邊緣的距離
screenX screenLeft
screenY screenTop

計算樣式

HTMLelement.style

使用樣式來獲取元素的大小以及定位是一種常見的操做,可是問題在於使用HTMLelement.style獲取的內容:

  • 是帶有css單位的字符串
  • 須要寫在內聯中才能夠獲取到

使用style獲取元素的大小或者寬高無疑是方便的,這裏返回的值和css模型是一致的.

window.getComputedStyle

這個API和HTMLelement.style類型,調用這個API返回CSSStyleDeclaration對象.

區別在於:

  • 只讀
  • 可使用css完整的名稱來獲取樣式,例如font-size
  • 不只計算內聯樣式還包括樣式表中的樣式

注意:當元素的樣式修改的時候對應的CSSStyleDeclaration也會實時同步,你不須要對一個元素進行連續獲取.

滾動相關

屬性

使用對象 API名稱 描述
window pageXoffset 視口相對於頁面內容區域左側的距離,在現代瀏覽器上該值可能返回一個雙精度浮點型
window pageYoffset 視口頂部於頁面內容區域頂部的距離,在現代瀏覽器上該值可能返回一個雙精度浮點型
window scrollX 同pageXoffset
window scrollY 同pageYoffset
MDN滾動參數兼容性參考

https://developer.mozilla.org...

方法

快速解釋:

適用對象 API名稱 描述
window scrollBy 相對於當前的滾動位置進行滾動到指定的位置
window scrollByLines 相對於當前的滾動位置按照行數進行滾動(非標準)
window scrollByPages 相對於當前的滾動位置按照頁數進行滾動(非標準)
window scroll 絕對滾動到某個位置上
window scrollTo 功能於scroll方法無異
window scrollMaxX 獲取水平方向滾動距離的極限(非標準)
window scrollMaxY 獲取垂直方向滾動距離的極限(非標準)
element scrollTo 用在元素上的scrollTo方法,功能於window上的方法無異.
element scrollBy 用在元素上的scrollBy方法,功能於window上的方法無異
element scroll 用在元素上的scroll方法,功能於window上的方法無異.
相關文章
相關標籤/搜索