詳解JS位置、寬高屬性之一:offset系列
圖一
不知道大家看到這張圖的第一感覺如何,反正我的感覺就是“這次第,怎一個亂字了得”。
既然我認為上圖太多太亂,那麼我就把offset、scroll、client分開說,希望能讓大家徹底弄清楚,今天只說offset。
一、關於offset,我們要弄明白什麼
在這裡我們可以看到,關於offset共有5個東西需要弄清楚:
1、offsetParent
2、offsetTop
3、offsetLeft
4、offsetWidth
5、offsetHeight
我們根據難易程度把以上5點分為三類來講解。
在分析之前,先來看段測試程式碼:
<body><style type="text/css"> body { border:20px solid #CCC; margin:10px; padding:40px; background:#EEE; } #test { width:400px; height:200px; padding:20px; background:#F60; border:5px solid #888; } </style> <div id="test"></div> <script> var test = document.getElementById("test"); test.innerHTML = "<p>Browser:" + navigator.userAgent + "</p>" + "<p>offsetWidth:" + test.offsetWidth + "</p>" + "<p>offsetHeight:"+test.offsetHeight+"</p>"+ "<p>offsetLeft:"+test.offsetLeft+"</p>"+ "<p>offsetTop:"+test.offsetTop+"</p>"; </script> </body>
這段程式碼在各個瀏覽器中的效果如圖:
圖二(IE6/7)
圖三(IE8/9/10)
圖四(Firefox)
圖五(Chrome)
二、offsetWidth與offsetHeight
大家可以看到,上面圖二~圖五中的共同點是 offsetWidth與offsetHeight是一致的,因此這裡放到地起講。
Returns the layout width of an element.
Typically, an element's
offsetWidth
is a measurement which includes the element borders, the element horizontal padding, the element vertical scrollbar (if present, if rendered) and the element CSS width.
也就是元素的可視寬度,這個寬度包括元素的邊框(border),水平padding,垂直滾動條寬度,元素本身寬度等。
offsetHeight跟offsetWidth類似,只是方向改為垂直方向上的。
只是我們的示例中沒有水平和垂直滾動條。另外經過測試可以發現,即使元素加上水平或垂直滾動條,offsetWidth跟offsetHeight的值是不會更改的,因為瀏覽器渲染時把滾動條的寬度(或高度)算在了元素本身的寬度(或高度)中了。
通過程式碼及圖中數值,我們不難看出:
offsetWidth=(border-width)*2+(padding-left)+(width)+(padding-right)
offsetHeight=(border-width)*2+(padding-top)+(height)+(padding-bottom)
對這兩個概念就總結到這裡,大家現在弄明白了嗎?
三、offsetLeft與offsetTop
offsetWidth與offsetHeight有個特點,就是這兩個屬性的值只與該元素有關,與周圍元素(父級和子級元素無關)。
然而,offsetLeft與offsetTop卻不是這樣,這兩個屬性與offsetParent有關,但在我們講到offsetParent之前,我們先不管offsetParent是什麼及怎麼判斷,我們只要知道offsetLeft和offsetTop與offsetParent有關就行了,上面的示例中offsetParent就是body。
MSDN上對offsetLeft的定義是:
Retrieves the calculated left position of the object relative to the layout or coordinate parent, as specified by the offsetParent property
也就是返回物件元素邊界的左上角頂點相對於offsetParent的左上角頂點的水平偏移量。從這個定義中我們可以明確地知道offsetLeft與當前元素的margin-left和offsetParent的padding-left有關。也就是說應該是:
offsetLeft=(offsetParent的padding-left)+(中間元素的offsetWidth)+(當前元素的margin-left)。
offsetTop=(offsetParent的padding-top)+(中間元素的offsetHeight)+(當前元素的margin-top)。
但通過上面的例子我們可以看到,當offsetParent為body時,對於offsetLeft與offsetTop的值有三種,分別是:IE6/7中的40,IE8/9/10 和 Chrome中的70,以及FireFox中的50。
通過這些數值我們可以知道,當offsetParent為body時情況比較特殊:
在IE8/9/10及Chrome中,offsetLeft = (body的margin-left)+(body的border-width)+(body的padding-left)+(當前元素的margin-left)。
在FireFox中,offsetLeft = (body的margin-left)+(body的padding-left)+(當前元素的margin-left)。
四、offsetParent
終於到offsetParent了。
offsetParent屬性返回一個物件的引用,這個物件是距離呼叫offsetParent的元素最近的(在包含層次中最靠近的),並且是已進行過CSS定位的容器元素。 如果這個容器元素未進行CSS定位, 則offsetParent屬性的取值為根元素的引用。
總的來說兩條規則:
1、如果當前元素的父級元素沒有進行CSS定位(position為absolute或relative),offsetParent為body。
2、如果當前元素的父級元素中有CSS定位(position為absolute或relative),offsetParent取最近的那個父級元素。
上面的示例就是第1條說的情況,我們來驗證一下:
我們把JS改為(添加了一行程式碼:紅色部分):
var test = document.getElementById("test"); test.innerHTML = "<p>Browser:" + navigator.userAgent + "</p>" + "<p>offsetParent:" + test.offsetParent.tagName + "</p>" + "<p>offsetWidth:" + test.offsetWidth + "</p>" + "<p>offsetHeight:"+test.offsetHeight+"</p>"+ "<p>offsetLeft:"+test.offsetLeft+"</p>"+ "<p>offsetTop:"+test.offsetTop+"</p>";
FireFox下的效果為:
圖六
在其他瀏覽器中效果相同,都是body。
我們再來驗證一下第2條,測試HTML如下:
<!DOCTYPE html> <html> <head> <title>Demo</title> </head> <body> <style type="text/css"> body { margin:0; padding:0; background:#EEE; } div,ul,li { margin:0; } li { height:20px; line-height:20px; } #test { width:400px; height:250px; padding:20px; background:#F60; border:10px solid #888; } #divtest { margin:30px; position:relative; left:50px; top:70px; padding:20px; } </style> <div id="divtest"> <ul> <li>Test</li> <li>Test</li> </ul> <div id="test"> </div> </div> <script> var test = document.getElementById("test"); test.innerHTML = "<p>Browser:" + navigator.userAgent + "</p>" + "<p>offsetParent:" + test.offsetParent.tagName + "</p>" + "<p>offsetWidth:" + test.offsetWidth + "</p>" + "<p>offsetHeight:"+test.offsetHeight+"</p>"+ "<p>offsetLeft:"+test.offsetLeft+"</p>"+ "<p>offsetTop:"+test.offsetTop+"</p>"; </script> </body> </html>
在FireFox中效果為:
圖七
在其他瀏覽器中offsetParent也是一致的。
在這裡我們也可以看到,第三點中給出的offsetLeft的計算公式是適用的。
小結
以上的總結希望能對大家有所幫助,在看完本文內容後再回過頭來看文章開頭部分的那張圖(只看offset)部分,是不是清楚了很多?
最後,對於offsetParent為body的情況,現在的主流瀏覽器IE8/9/10和Chrome及Firefox都跟定義
offsetLeft=(offsetParent的padding-left)+(中間元素的offsetWidth)+(當前元素的margin-left)。offsetTop=(offsetParent的padding-top)+(中間元素的offsetHeight)+(當前元素的margin-top)。
的不一樣,對於這一點我也沒有弄明白,如果有朋友知道請不吝賜教。
相關推薦
詳解JS位置、寬高屬性之一:offset系列
很多初學者對於JavaScript中的offset、scroll、client一直弄不明白,雖然網上到處都可以看一張圖(圖1),但這張圖太多太雜,並且由於瀏覽器差異性,圖示也不完全正確。 圖一 不知道大家看到這張圖的第一感覺如何,反正我的感覺就是“這次第,怎一個亂字了
css3動畫屬性詳解之transform、transition、animation
本文轉自segmentfault.com/a/1190000004460780#articleHeader5 css3動畫屬性詳解:關於CSS3製作動畫的幾個屬性:變形(transform)、轉換(transition)和動畫(animation)。 一、transform 屬性:
手把手教你ExtJS從入門到放棄——篇十七(示例14: Ext.js方法詳解之typeOf、isEmpty、isIterable、isFunction、isArray... Iterate)
ExtJS底層就是JS不要想得很難,如果根據需求可以適當看看原始碼,這裡我就不帶著看了 typeOf 返回物件的型別,如下猜猜結果 是string,number哦 isEmpty、isIterable、isFunction、isArray學過JS的這幾個方法就不用多講了 分
js 元素的各種位置尺寸寬高
元素.offsetLeft[Top]:只讀 屬性 當前元素到定位父級的距離(偏移值) 到當前元素的offsetParent的距離 如果沒有定位父級 offsetParent -> body offsetLeft -> h
linux命令詳解(19)修改檔案屬性 lsattr、chattr命令詳解
修改檔案屬性 Linux檔案系統裡的檔案和目錄全都關聯使用者、使用者組和其他使用者的讀、寫和執行許可權。此外,還可能存在其他特定檔案系統型別才有的檔案和目錄相關屬性。 ext2和ext3檔案系統檔案可以選用一些特殊屬性。使用lsattr命令可以列出這些屬性。大部分屬性都晦澀
js得到螢幕寬高、頁面寬高 (window.screen.availHeight)等
window.screen.availWidth 返回當前螢幕寬度(空白空間) window.screen.availHeight 返回當前螢幕高度(空白空間) window.screen.width 返回當前螢幕寬度(解析度值) window.screen.heig
Android layer-list的屬性和使用詳解(陰影、邊框效果)
layer-list用於多個圖層堆疊,可以完成陰影效果 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/
Vue.js 執行環境搭建詳解及vue、node基礎知識普及
Vue.js 是一套構建使用者介面的漸進式框架。他自身不是一個全能框架——只聚焦於檢視層。因此它非常容易學習,非常容易與其它庫或已有專案整合。在與相關工具和支援庫一起使用時,Vue.js 也能完美地驅動複雜的單頁應用。 在配置環境之前呢,有些基礎的東西還是要和大家普及
詳解js跨域
-name tor adding code 填充 父域 allow mes document 什麽是跨域? 概念:只要協議、域名、端口有任何一個不同,都被當作是不同的域。 對於端口和協議的不同,只能通過後臺來解決。URL 說明
#26 Linux kernel(內核)詳解與uname、lsmod、modinfo、depmod、insmod、rmmod、modprobe...命令用法
linux kernel(內核)詳解與uname、lsmod、modinfo、depmod、insmod、rmmod、modprobe...命令用法Linux kernel: 內核設計流派: 單內核設計,但是充分借鑒了微內核體系設計的優點,為內核引入了模塊化機制,內核高度模塊化; 內核被模塊化之
js 獲取圖片寬高 和 圖片大小
src 查看 nts 執行 input java image 創建 wid 獲取要查看大小的img varimg_url = ‘http://img5.imgtn.bdimg.com/it/u=4267222417,1017407570&fm=
轉-Linux啟動過程詳解(inittab、rc.sysinit、rcX.d、rc.local)
dha mage 模塊 都是 交換 如何配置 mas 完全 打開 http://blog.chinaunix.net/space.php?uid=10167808&do=blog&id=26042 1)BIOS自檢2)啟動Grub/Lilo3)加載內
詳解linux運維工程師高級篇(大數據安全方向)
向導 未使用 上傳 itl 條件 ear 實測 port 擁有 詳解linux運維工程師高級篇(大數據安全方向) hadoop安全目錄:kerberos(已發布)elasticsearchknoxoozierangerapache sentry簡介: 從運維青銅
js獲取各種寬高
fun cti oct eve page 部分 屬性 char lan 1.窗口和瀏覽器 window.innerWidth、window.innerHeight 瀏覽器內部可用寬高 window.outerWidth、window.outerHeight 瀏覽器整
OSPF詳解-3 鄰接、度量值
MF 鏈路狀態路由協議 log 刪除 使用 依次 img 規則 版本 **一、OSPF鄰接關系 運行鏈路狀態路由協議的路由器必須首先與選定的鄰居路由器建立鄰接關系,這是通過與鄰居路由器交換Hello分組來實現的。 1.鄰接路由器建立步驟 路由器建立鄰接關系的步驟如下:
python0.16------構造函數/析構函數/self詳解/重寫/訪問限制/對象屬性和類屬性/@property/運算符重載
動態添加 輸出 自然 表示 不可 spa type 錯誤 特點 構造函數:__init__()引子:因為每個人一出生都是不一樣的。因此,如果在Person類中直接給類元素賦值有問題,它會導致每個人的初始狀態相同,這不符合大自然的邏輯。應該根據每個人的特點,給每個出生的人
詳解Docker架構、鏡像、容器及資源限制
開啟 獲取 roc 隔離 圖片 詳解 inf cobbler ghost Docker概述 Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後發布到任何流行的Linux機器上,也可以實現虛擬化,容器是完全使用沙箱機制,相互
詳解Mysql事務、索引、視圖
詳細信息 fad mysql 出現一次 text esc 這一 虛擬 內存 索引簡介 索引是為了加速對表中數據行的檢索而創建的一種分散的存儲結構。索引是針對表而建立的,它是由數據頁面以外的索引頁面組成的,每個索引頁面中的行都會含有邏輯指針,以便加速檢索物理數據。 索引作用
詳解js正則表達式語法介紹
技術 invalid 我想 不同 小結 小括號 字符 rip 空字符串 1. 正則表達式規則 1.1 普通字符 字母、數字、漢字、下劃線、以及後邊章節中沒有特殊定義的標點符號,都是"普通字符"。表達式中的普通字符,在匹配一個字符串的時候,匹配與之相同的一個字符。
深度學習——優化器演算法Optimizer詳解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)
在機器學習、深度學習中使用的優化演算法除了常見的梯度下降,還有 Adadelta,Adagrad,RMSProp 等幾種優化器,都是什麼呢,又該怎麼選擇呢? 在 Sebastian Ruder 的這篇論文中給出了常用優化器的比較,今天來學習一下:https://arxiv.org/pdf/160