彻底搞懂 offsetX、scrollX、clientX 的区别
無論在 iOS 還是前端開發中,關于如何定位一個元素是必須要掌握的知識,而在前端中,元素定位比較難理解,我們今天一起學習下。
在 DOM 設計中,主要通過這些 API 來確定某個元素的具體位置。
offsetTop, offsetLeft, offsetWidth, offsetHeight,
scrollTop, scrollLeft, scrollWidth, scrollHeight,
clientTop, clientLeft, clientWidth, clientHeight,
為什么會有這么多屬性來定位一個元素?
我覺得和盒子模型有很大關系,一個盒子就是一個區域,包含 margin、border、padding 和 content。上面 6 個屬性可以非常容易定位元素。
有沒有類似 iOS 中 frame 的概念?
答案是有的。可以通過 Element.getBoundingClientRect() 來確定元素在可視區域中的位置。
這些屬性究竟有什么不同,我們一一分析:
1、offsetX —— 相對誰偏移了多少?
offsetX 是 HTMLElement 的只讀屬性,不可以修改。offset 有“偏移” 的意思,你可能會把這個屬性想成與滾動有關,其實與滾動沒半毛錢關系。我們先看 offsetTop 這個屬性,它表示當前元素頂部到 offsetParent 節點的距離。這里關鍵點是?offsetParent,它是指當前元素最近的使用 position 不為 static 的祖先節點,如果沒有使用 position 的祖先節點,它的值將是 body 節點(這個值有可能也是 null,如果出現這些極端情況可以查 MDN)。其實關鍵點是「相對誰偏移了多少的問題」。一圖勝千言。
上圖中,由于小人的父元素 div 是 positioned,故它的 offsetParent 為 div,而不是 body,offsetTop 是指小人頂部距離 div 距離(圖中紅線部分)。
同理 offsetLeft 是距離左邊的距離,只要明白了 top,left 屬性也就明白了。
offsetWidth 和 offsetHeight 指寬高,包含 boder 、 padding 和 content。
總之,offset 相關的屬性指元素相對某個元素的位置,與滾動沒有半毛錢關系。
2. scrollX ——?滾動了多少?
與 scroll 相關的屬性是?Element 的屬性,offsetTop、offsetLeft 可讀可寫,offsetWidth、offsetHeight 只讀。
scroll 才真正與滾動相關,我們以豎直方向滾動為例。
只有元素可以滾動 scrollTop 才會有值,否則為 0,也就是說當子元素的高度大于父元素時,設置父元素的 overflow 為 scroll 才會生效。
當 子div 的高度超出 父div 時,父div 需要通過把?overflow?設置為?scroll,這時候 子div 才可以滾動。這里有一點需要注意,圖中所標記的 scrollTop 的屬性是 子div 的還是 父div 的?歡迎留言說出你的答案。
scrollTop 的值可以修改,表示在滾動區域中,豎直方向滾動了多少。通常通過修改這個值來實現讓某個元素滾動到指定位置。
關于 scrollHeight 這個也需要特別留意,父 div 的 scrollHeight 是通過子div 計算的,表示可滾動的高度。
scrollWidth 與 scrollHeight 類似。我特意寫了一個 demo,想要搞懂這個必須通過 demo 實踐。
3.?clientX? —— 我自身的位置
它是 Element 的屬性。client 相關的屬性描述的是自身的位置,它沒有相對元素。
clientTop 就是 border-top 的值,clientLeft 就是 border-left 的值。而 clientWidth 和 clientHeight 都不包含 border。
4.?Element.getBoundingClientRect() —— 相對可視區域的位置
通過這個 API 獲取元素相對可視區域的位置,返回值是浮點數。其中,大多數情況下 x 與 left 相等,y 與 top 相等,只有當 width 或 height 為負數的時候會有區別。left = x + with,top = y + height。圖中黃色區域為邊框。
注意觀察 bottom 和 right 的值。
5. 少不了 demo
我寫了一個輸出這些屬性的方法,方便同時查看這些屬性的值:
var logBySelector = function (id) {let elm = document.querySelector(id);logFrame(elm);elm.onscroll = function () {logFrame(elm);if (elm.scrollHeight - elm.scrollTop === elm.clientHeight) {console.log('到底了');}else if (elm.scrollTop === 0) {console.log('到頂了');}}
};var logFrame = function (elm) {console.log(elm, '-------------------------');console.log(elm.getBoundingClientRect());for (key in elm) {let whiteList = ['offsetTop', 'offsetLeft', 'offsetWidth', 'offsetHeight','scrollTop', 'scrollLeft', 'scrollWidth', 'scrollHeight','clientTop', 'clientLeft', 'clientWidth', 'clientHeight','offsetParent'];if (whiteList.indexOf(key) !== -1) {console.log(key, ' = ', elm[key]);}}
}
demo 地址:https://github.com/lefex/FE/tree/master/%E7%AC%AC%E4%BA%94%E9%98%B6%E6%AE%B5
本文講解了元素相關的位置屬性,這幾個屬性容易弄混,我特意為大家準備了 demo。這些知識與前面講的 CSS 布局 堅持14天學懂CSS布局(領電子書),盒子模型 第10天:撐起CSS布局的半壁江山---盒子模型 有很大關系。當然我們還需要一節內容來實踐一下。大家加油。
推薦閱讀:
我是一顆樹 · DOM
回到工位“我”悟出了 DOM 設計的精華
打通 DOM 的設計架構
兩種方法輕松找到 DOM 元素
總結
以上是生活随笔為你收集整理的彻底搞懂 offsetX、scrollX、clientX 的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 文本格式显示折线图,linu
- 下一篇: 鸿蒙初开踏青时主要内容,鸿蒙初开踏青时