思維導圖:
一 offset 系列
1.1 定位元素
定位元素(positioned element)是指該元素計算後位置(position)屬性為 relative, absolute,fixed 或 sticky 的一個元素。同時定位屬性又細分為以下幾種:
- 相對定位元素(relatively positioned element): 指該元素計算後位置(position)屬性為relative 的元素
- 絕對定位元素(absolutely positioned element): 指該元素計算後位置(position)屬性為 absolute 或 fixed 的元素
- 粘性定位元素(stickily positioned element): 指該元素計算後位置(position)屬性為 sticky 的元素
對于絕對定位元素(position 屬性為 absolute 或 fixed 的元素 ), 在未設定 height 和 width 或者為 auto 的情況下,允許通過 top bottom left right 來填充容器可用的空間, 隻是 top bottom left right 的參考對象不同而已;
1.2 Element.offsetParent
Element.offsetParent 是一個隻讀屬性, 傳回目前元素最近的一個父級定位元素。同時又有下列幾種特殊情況:
- 如果目前元素沒有父級定位元素,則 offsetParent 為最近的标準單元格元素( td 元素)
- 如果目前元素最近也沒有标準單元格元素,則為 body 元素。(有種說法: 标準模式下為 offsetParent 為 html 元素,quirks 模式下但是經過測試好像都是 body 元素)
- 在 WebKit 為核心的浏覽器上,如果元素是隐藏的(style.display=‘none’)或者元素 style.position=‘fixed’,則該元素 offsetParent 為 null
- 在IE(9)上隻有當元素 style.position=‘fixed’ 時 offsetParent 才會傳回 null, 即使元素 display = ‘none’ 也是不會影響傳回結果
1.3 Element.offsetLeft && Element.offsetTop
Element.offsetLeft 和 Element.offsetTop 是一個隻讀屬性,傳回目前**元素邊界(border)**相對于Element.offsetParent 節點的偏移的像素值。
- 示意圖:
- 上圖示範代碼:
<style>
#parent{
position: relative;
border: 30px solid red;
padding: 30px;
width: 200px;
height: 200px;
}
#child{
border: 30px solid blue;
padding: 30px;
margin: 20px;
width: 20px;
height: 20px;
}
</style>
<div id="parent">
<div id="child"></div>
</div>
<script>
const dom = document.getElementById('child');
console.log(dom.offsetParent); // <div id="parent"></div>
console.log(dom.offsetTop); // 50
</script>
1.4 Element.offsetWidth && Element.offsetHeight
Element.offsetWidth 和 Element.offsetHeight 是一個隻讀屬性,傳回一個元素布局的寬高(元素布局包括:border、滾動條、padidng、内容塊), 該屬性傳回的值為一個四舍五入的整數
- 示意圖:
- 上圖示範代碼:
<style>
#parent{
margin: 10px;
border: 20px solid red;
padding: 20px;
width: 100px;
height: 100px;
overflow: scroll;
}
#child{
width: 100%;
height: 100%;
background: #eee;
}
</style>
<div id="parent">
<div id="child"></div>
</div>
<script>
const dom = document.getElementById('parent');
console.log(dom.offsetParent); // <body></body>
console.log(dom.offsetHeight); // 180
console.log(dom.offsetWidth) // 180
</script>
1.5 内聯元素下的特殊行為
上文關于 Element offset 系列屬性的描述都是針對塊級元素進行的,至于内聯元素又有一定的差別:
- 示意圖:
- 上圖示範代碼:
<style>
#parent{
position: relative;
width: 200px;
border: 10px solid red;
}
#Placeholder{
display: inline-block;
width: 100px;
}
#child{
border: 10px solid blue;
padding: 10px;
}
</style>
<div id="parent">
<span id="Placeholder">占位元素</span>
<span id="child">
要計算的元素要計算的元素要計算的元素
</span>
</div>
<script>
const dom = document.getElementById('child');
console.log(dom.offsetParent);
console.log(dom.offsetTop); // -12
console.log(dom.offsetLeft); // 104
console.log(dom.offsetWidth); // 192
console.log(dom.offsetHeight); // 102
</script>
二 client 系列
- Element.clientTop 和 Element.clientLeft 擷取可視區域的偏移值(實際上就等于元素上下 border值)
- 四舍五入(整數)後的結果; Element.clientWidth 和 Element.clientHeight擷取可視區域(padding + 元素内容區域的寬高,不包含滾動條)的寬高
- 示意圖:
- 上圖示範代碼:
<style>
#parent{
margin: 10px;
border: 20.5px solid red;
padding: 20px;
width: 100px;
height: 100px;
overflow: scroll;
}
#child{
width: 100%;
height: 100%;
background: #eee;
}
</style>
<div id="parent">
<div id="child"></div>
</div>
<script>
const dom = document.getElementById('parent');
console.log(dom.clientTop); // 21
console.log(dom.clientLeft); // 21
console.log(dom.clientWidth); // 125
console.log(dom.clientHeight); // 125
</script>
三 scroll 系列(用于對可滾動元素進行求值)
3.1 Element.scrollTop && Element.scrollLeft(可寫)
Element.scrollTop 和 Element.scrollLeft用于擷取或設定元素被卷起的寬高(子元素頂部或左側到目前元素可視區域頂部或左側的距離)
- 示意圖:以 scrollTop 為例
- 上圖示範代碼:
<style>
#parent{
width: 200px;
height: 200px;
padding: 50px;
background: #eee;
overflow: auto;
}
#child {
height: 400px;
margin: 50px;
padding: 50px;
width: 20px;
background: #ccc;
}
</style>
<body>
<div id="parent">
<div id="child"></div>
</div>
</body>
<script>
window.onload = () => {
const dom = document.getElementById('parent');
dom.onscroll= () => {
console.log(dom.scrollTop);
}
}
</script>
補充:
- 對于不可滾動的元素 Element.scrollTop 和 Element.scrollLeft 值為 0
- 如果給scrollTop(scrollLeft) 設定的值小于0,那麼 scrollTop(scrollLeft) 的值将變為0。
- 如果給scrollTop(scrollLeft) 設定的值大于元素内容最大寬度,那麼scrollTop(scrollLeft)的值将被設為元素最大寬度(高度)。
3.2 Element.scrollWidth && Element.scrollHeight
- Element.scrollWidth 和 Element.scrollHeight 是隻讀屬性, 表示元素可滾動區域的寬高; 實際上又等于clientHeight/clientWidth + 未顯示在螢幕中内容的寬高;
- 它們的值等于元素在不使用水準滾動條的情況下适合視口中的所有内容所需的最小寬度。
- 測量方式與clientWidth(clientHeight) 相同:它包含元素的内邊距,但不包括邊框,外邊距或垂直滾動條(如果存在)。它還可以包括僞元素的寬度,例如::before或::after。
- 如果元素的内容可以适合而不需要水準滾動條,則其 scrollWidth等于 clientWidth; (最小值為元素的可視區域寬高: clientWidth (clientHeight))
- 示意圖:以 scrollHeight 為例
- 上圖示範代碼:
<style>
#parent{
width: 200px;
height: 200px;
padding: 50px;
background: #eee;
overflow: auto;
}
#child {
height: 400px;
margin: 50px;
padding: 50px;
width: 20px;
background: #ccc;
}
</style>
<body>
<div id="parent">
<div id="child"></div>
</div>
</body>
<script>
window.onload = () => {
const dom = document.getElementById('parent');
console.log(dom.scrollHeight); // 700
}
</script>
補充:
- 雖然 scrollWidth 計算方式和 scrollHeight 是一樣的, 但是如果在可滾動元素中其子元素使用了margin-right 則會發生 margin 塌陷等問題,這時實際計算出的scrollWidth會有所不同