搞清clientHeight、offsetHeight、scrollHeight、offsetTop、scrollTop

轉載自:https://www.imooc.com/article/17571

網頁可見區域高:document.body.clientHeight

網頁正文全文高:document.body.scrollHeight
網頁可見區域高(包括邊線的高):document.body.offsetHeight
網頁被卷去的高:document.body.scrollTop

屏幕分辨率高:window.screen.height

每個HTML元素都具有clientHeight offsetHeight scrollHeight offsetTop scrollTop 這5個和元素高度、滾動、位置相關的屬性,單憑單詞很難搞清楚分別代表什么意思之間有什么區別。通過閱讀它們的文檔總結出規律如下:
clientHeight和offsetHeight屬性和元素的滾動、位置沒有關系它代表元素的高度,其中:
clientHeight:包括padding但不包括border、水平滾動條、margin的元素的高度。對于inline的元素這個屬性一直是0,單位px,只讀元素。


圖片描述

offsetHeight:包括padding、border、水平滾動條,但不包括margin的元素的高度。對于inline的元素這個屬性一直是0,單位px,只讀元素。


圖片描述

接下來討論出現有滾動條時的情況:
當本元素的子元素比本元素高且overflow=scroll時,本元素會scroll,這時:
scrollHeight: 因為子元素比父元素高,父元素不想被子元素撐的一樣高就顯示出了滾動條,在滾動的過程中本元素有部分被隱藏了,scrollHeight代表包括當前不可見部分的元素的高度。而可見部分的高度其實就是clientHeight,也就是scrollHeight>=clientHeight恒成立。在有滾動條時討論scrollHeight才有意義,在沒有滾動條時scrollHeight==clientHeight恒成立。單位px,只讀元素。


圖片描述

scrollTop: 代表在有滾動條時,滾動條向下滾動的距離也就是元素頂部被遮住部分的高度。在沒有滾動條時scrollTop==0恒成立。單位px,可讀可設置。
offsetTop: 當前元素頂部距離最近父元素頂部的距離,和有沒有滾動條沒有關系。單位px,只讀元素。


圖片描述

offsetTop: 當前元素頂部距離最近父元素頂部的距離,和有沒有滾動條沒有關系。單位px,只讀元素。


圖片描述

以下內容轉載自:
https://blog.csdn.net/shibazijiang/article/details/103894498

我們開發web代碼的時候,經常會遇到各種高度的計算. 因為總是忘記幾者之間得區別,每次都要現查,這次通過這篇文章徹底搞明白這幾個長度的區別.


在這里插入圖片描述

1.定義說明

條目 含義 圖示
clientHeight 元素的像素高度,包含元素的高度+內邊距,不包含水平滾動條,邊框和外邊距
在這里插入圖片描述
offsetHeight 元素的像素高度 包含元素的垂直內邊距和邊框,水平滾動條的高度,且是一個整數
在這里插入圖片描述
scrollHeight 元素內容的高度,包括溢出的不可見內容
在這里插入圖片描述
offsetLeft 返回元素左上角相對于offsetParent的左邊界的偏移像素值

注意點

1.對塊級元素來說,offsetTop、offsetLeft、offsetWidth 及 offsetHeight 描述了元素相對于 offsetParent 的邊界框。但是文本框不是如此.文本框的offsetLeft和offsetTop是第一個文本框的左偏移和上偏移.

2.offsetParent元素指改元素的定位元素以及最近的table,td,th,body.
可見,offsetParent和position屬性的包含塊概念類似.大部分場景下可以通用.

3.offsetTop和offsetLeft都是相對于其內邊距邊界的.

offsetLeft和left屬性的區別

1.position為fixed時值不同
當position為fixed的時候,offsetLeft的值將會是null,而left此時一般有確定的數字值.
2.相對邊距不同
offerset的是相對于offsetParent的內邊距邊界,left是相對于包含塊的外邊距邊界.
3.包含塊有區別
offerset相對與定位的祖先元素或者 table/td/th/body等祖先元素,left僅僅是相對于定位祖先元素+body

clientHeight與offsetHeight的區別

clientHeight僅僅包含內邊距+高度,offsetHeight包含內邊距+滾動條+邊框
所以可以這樣說: clientHeight+滾動條高度+邊框 = offsetHeight

參考資料:

1.offsetHeight官方說明
https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/offsetHeight

2.clientHeight官方說明
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/clientHeight

二、js事件對象Event獲取pageX,clientX,screenX,offsetX,layerX的方式與區別

pageX:
鼠標在頁面上的位置,從頁面左上角開始,即是以頁面為參考點,同一個元素坐標不隨滑動條移動而變化

clientX:
鼠標在頁面上可視區域的位置,即是以瀏覽器滑動條此刻的滑動到的位置為參考點,同一個元素坐標隨滑動條移動而變化.

注:
1、如果元素位于body中,e.clientX + document.body.scrollLeft - document.body.clientLeft = e.pageX,
2、e.clientX包括了body的邊框,document.body.scrollLeft也包括了body邊框,body表框運算重復,減去document.body.clientLeft,即去掉重復的body邊框

screenX:
獲取到的是觸發點相對顯示器屏幕左上角的距離,不隨頁面滾動或瀏覽器移動而改變

offsetX:
獲取到的是鼠標觸發點相對于目標事件元素(被觸發DOM)左上角的距離(確切的說是到邊框外邊界的距離),其中在IE中以內容區左上角為基準點不包括邊框,如果觸發點在邊框上會返回負值,而chrome中以邊框左上角為基準點。

layerX:
獲取到的是鼠標觸發點相對于offsetParent元素左上角的距離(確切的說是到邊框外邊界的距離),包括中間所有元素的padding、margin、border及元素寬度值之和),其中在IE中以內容區左上角為基準點不包括邊框,如果觸發點在邊框上會返回負值,而chrome中以邊框左上角為基準點。

注:關于offsetParent元素
1、如果當前元素的祖先元素沒有進行CSS定位(position為absolute或relative),offsetParent為body。
2、如果當前元素的祖先元素(包括當前元素)中有CSS定位(position為absolute或relative),offsetParent取最近的那個祖先元素(包括當前元素)。

總結:
1、使用pageX獲取帶滾動條的到頁面邊緣尺寸
2、使用clientX獲取到瀏覽器可是區域的尺寸,沒有滾動條,pageX == clientX
3、使用screenX獲取到屏幕邊緣尺寸
4、使用offsetX獲取到當前元素邊緣尺寸
5、使用layerX獲取到offsetParent邊緣尺寸

三、頁面元素坐標和偏移(clientX/pageX/screenX/layerX/offsetWidth/scrollWidth/clientWidth等)相關整理

鼠標事件都是在特定位置發生的,我們可以通過event事件對象的各種屬性來獲得事件發生的坐標位置,有相對于視口的,有相對于整個文檔的,同樣頁面元素的位置也有相對視口的,也有滾動后的,這些都比較容易混淆,所以整理在這里,備忘,待查。

1.客戶區坐標位置(clientX/clientY)

我們可以通過event事件對象的clientX/clientY屬性獲得事件發生時鼠標指針在視口中的水平和垂直坐標。

示意圖:

image

2.屏幕坐標位置(screenX/scrennY)

通過event事件對象的screenX/screenY屬性,可以獲取鼠標事件發生時鼠標光標相對于整個電腦屏幕的坐標信息。

示意圖:

image

clientX/clientY和screenX/screenY區別demo:clientX/clientY和screenX/screenY區別demo

demo 源代碼戳這里:https://github.com/demo.html

3.頁面坐標位置(pageX/pageY)

通過事件對象的pageX/pageY屬性可以獲得鼠標事件發生時鼠標光標相對于整個文檔元素的坐標位置(包含滾動)。

在頁面沒有滾動的情況下,通常pageX/pageY的值與clientX/clientY的值相等。

4.layerX/layerY

事件對象還有個不那么常見的屬性,那就是layerX/layerY,他是對于絕對定位元素來說的,相對于當前點擊元素的左上角定位的。當頁面上的元素時相對定位(position:relative)的時候,通常pageX/pageY和layerX/layerY的值是相同的,但是當元素絕對定位(position:absolute)了的時候,layerX/layerY就將鼠標光標位置相對于本身的左上角定位了。

下面demo有助于理解,猛戳:

pageX\pageY & layerX\layerY示意demo:pageX\pageY & layerX\layerY

demo代碼猛戳這里:https://github.com/pageXandLayerX.html

5.偏移量:(offsetWidth/offsetHeight/offsetLeft/offsetTop)

元素的偏移量(offsetLeft/offsetTop)是相對于它的直接父元素來說的。

   [元素的可見大小由其高度和寬度決定,這包括所有的內邊距(padding)、滾動條和邊框(border)大小(注意這里面不包括margin喔,因為margin是透明的,一般使用它控制元素之間的間隔)。這是為什么呢,因為吧,可以一試,如果我們給元素添加背景的話,那么背景會被應用 于由內容和內邊距組成的區域,而添加邊框(border)會在內邊距(padding)的區域外邊加一條線,margin透明,當然不在可見范圍內啦。]

示意圖:

image

Tips:

1.如果要想知道某個元素在頁面上的偏移量,將這個元素的offsetLeft和offsetTop與其offsetParent的相同屬性相加,如此循環至根元素,就可以得到一個基本準確的值。

2.如果有些div他的offsetParent是<body>的話,那么也可以嘗試getElementLeft()和getElementTop()方法,不出意外地話會返回跟offsetLeft和offsetTop相同的值。

3.所有這些偏移量都是只讀的,而且每次訪問的時候都需要重新計算,要注意性能問題。

6.客戶區的大小(clientWidth/clientHeight)

  元素的客戶區的大小就是指元素內容及其內邊距所占空間的大小(滾動條占用的空間不計算在內)。(clientWidth=width+padding(left、right);clientHeight=height+padding(top、bottom))

clientWidth與offsetWidth區別示例:[clientWidth與offsetWidth區別](http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/refs/clientWidth.htm)

7.滾動大小(scrollWidth/scrollHeight/scrollLeft/scrollTop)

 有些元素,即使沒有執行任何代碼也會自動的添加滾動條,如<html>,但是另外一些元素,則需要通過css的overflow屬性進行設置才能滾動。

 通常認為<html>元素是在web瀏覽器的視口中滾動的元素(ie6之前版本運行在混雜模式下是<body>元素,這也是上面計算視口大小代碼if,else的原因),因此帶有垂直滾動條的頁面總高度就是document.documentElement.scrollHeight。

 ![image](https://upload-images.jianshu.io/upload_images/23628926-e97e6f9b47af590e.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

當overflow屬性設置為 auto時,內容可以超過元素的尺寸,并顯示滾動條。這時就可以使用scrollwidth屬性來檢索內容的寬度范圍內的元素。

MSDN上找到了相關的例子:scrollWidth屬性示例

更具體的信息,可以查看這里:MSDN scrollWidth

Tips:

在確定文檔的總高度時,必須取得scrollWidth、clientWidth和scrollHeight、clientHeight中的最大值,這樣才能保證在跨瀏覽器的情況下取得較為準確的結果。

8.window.scrollX/window.scrollY與window.pageXOffset/window.pageYOffset

window.scrollX/window.scrollY返回的是整個文檔document在水平和豎直方向滾動了的距離。

window.pageXOffset/window.pageYOffset相當于window.scrollX/window.scrollY的別名一樣的。也就是說:
window.pageXOffset == window.scrollX; // 總是返回真

但在跨瀏覽器的情況下,盡量使用window.pageXOffset/window.pageYOffset比較好。

所以為了保險起見,使用下面這樣的代碼來判斷文檔在垂直和水平防線滾動的距離比較好:

var x = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft; var y = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;

9.window.innerHeight/window.innerWidth

window.innerHeight/window.innerWidth記錄了視口內文檔元素的實際高度和寬度,實際上還有window.outerHeight/window.outerWidth。

下圖可以很好地區分兩者:

image

另外,如果頁面滾動了也不會影響他的innerHeight和innerWidth值:

image
image

此外,如果頁面中有frameset時:

var intFrameHeight = window.innerHeight; // or

var intFrameHeight = self.innerHeight;
// will return the height of the frame viewport within the frameset

var intFramesetHeight = parent.innerHeight;
// will return the height of the viewport of the closest frameset

var intOuterFramesetHeight = top.innerHeight;
// will return the height of the viewport of the outermost frameset

10.getBoundingClientRect()方法

   getBoundingClientRect用于獲得頁面中某個元素的左,上,右和下分別相對瀏覽器視窗的位置。getBoundingClientRect是DOM元素到瀏覽器可視范圍的距離(不包含文檔卷起的部分)。該函數返回一個Object對象,該對象有6個屬性:top,lef,right,bottom,width,height;這里的top、left和css中的理解很相似,width、height是元素自身的寬高,但是right,bottom和css中的理解有點不一樣。right是指元素右邊界距窗口最左邊的距離,bottom是指元素下邊界距窗口最上面的距離。

  通過這個方法可以比較方便的獲取頁面元素的位置:
    var X= this.getBoundingClientRect().left+document.documentElement.scrollLeft;
    var Y =this.getBoundingClientRect().top+document.documentElement.scrollTop;

關于這個方法MSDN上有詳細的解釋:getBoundingClientRect()方法

總結:

上面那些屬性都是很容易搞混的。而且也要注意不同的瀏覽器中可能存在的差別,使用的時候測試一下就能更準確的應用了。

搞清楚了上面這些相關屬性和方法,應該就能理解小胡子寫給我的這個demo了: js原生拖放

源代碼在這里:https://github.com/dragdemo.html

整理這篇文章的契機,就是我在實現原生的拖放功能。

備忘,待查。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容