jQuery - 元素的位置與大小

寬度、高度相關

width () 與 height ()

在 jQuery,width () 與 height () 方法回傳元素的內容區域寬度與高度,不包括內距(padding)、邊框(border),它與 box-sizing 設定值的有關係。

css (‘width’) 與 width () 在 box-sizing:content-box,兩者取的值一樣(因為都是指內容區域的寬度),差別在於 css (‘width’) 是有數字的字串 ‘px’,width () 只有數字。在設定為 box-sizing:border-box 時,css (‘width’) 依舊是直接取得 css 設定的 width 值(會包含 border、padding),而 width () 則必須要扣除掉 padding、border,依舊指的是取得內容區域的寬度。

設定 width (value) 與 height (value) 時,可以是 數字px%auto。如果傳入的是數字(未設定單位),視為預設以 px 為單位的尺寸大小,如果傳入的是字串值,會被用作 CSS width 或 height 屬性的值,因此可以套用任何 CSS 允許的單位,但不能設定 Window 或 Document 物件的寬度或高度,它們是唯讀

$(selector).height()
$(selector).height(value)
$(selector).height(function(index, currentValue){…})

$('.box').width() // 取得寬度
$('.box').width(100) // 設置寬度,數值表示 px
$('.box').width('50%') // 設置寬度,可使用字串

// 以下兩者不是元素,不需要考慮 padding、border
$(window).height() // 取得視窗高度
$(document).height() // 取得文件高度

// 可以使用函式
$('.box').height(function (index, currentValue) {
if (index == 1) {
return Math.random() * 1000
}
})

innerWidth () 與 innerHeight ()

在 box-sizing:content-box 設定下,innerWidth () 與 innerHeight () 回傳元素的寬度或高度(內容區域的寬、高)加上它內距(padding),但不包括邊框(border),但在 box-sizing:border-box 設定下,由於 padding 已經包含在 CSS 的 width、height,因此只會取得 width、height 值,它們不允許使用在 window、document。但可以用 width ()、height 來獲取。

與 JavaScript 的 clientWidth、clientHeight 屬性一樣。

$(selector).innerHeight()
$(selector).innerHeight(value)
$(selector).innerHeight(function(index,oldValue){ … })

outerWidth () 與 outerHeight ()

在 box-sizing:content-box 設定下,outerWidth () 與 outerHeight () 通常回傳元素的寬度或高度,加上內距(padding)、邊框(border),但在 box-sizing:border-box 設定下,由於 padding、border 已經包含在 CSS 的 width、height,因此只會取得 width、height 值,若傳入 true 值給上面任何一個方法,它們也會將該元素外距(margin)的大小計算在內。例如 outerWidth (true),預設是 false。

與 JavaScript 的 offsetWidth、offsetHeight 屬性一樣。

元素座標

offset()

返回元素視窗左上角至該元素邊框的座標偏移距離,它只以視窗計算至元素邊框的座標偏移距離,但如果有設定 margin,需與 top、bottom、left、right 加入計算,即便內部子元素用此方法,計算方式也是從視窗開始計算。offset () 可以加入物件參數回傳這個物件的 left 與 top 屬性(存有元素 X 與 Y 的座標數字)。如果使用 top、left 屬性,它會設定所指定的位置。

const pos = $('.box').offset() // 回傳一個紀錄 top、left 屬性的物件。
console.log(pos) // {top: 10, left: 10}

$(selector).offset()
$(selector).offset().top
$(selector).offset().left
$(selector).offset( {top:value,left:value} )
$(selector).offset( funnction(index, currentPosObject){ … } )

使用函式,返回要設置的坐標的函數。接收集合中元素的索引作為第一個參數,當前坐標作為第二個參數。該函數應該返回一個具有新的 top 和 left 屬性的對象。

注意,與 JavaScript 的 offsetTop、offsetLeft 屬性不同,即便它們名字很像,JavaScript 的 offsetTop、offsetLeft 與 jQuery 的 position () 一樣,與父元素位置有相對關係。 而且它們都是唯讀屬性,無法設置。

position()

position () 可以獲取定位的偏移量(與 JavaScript 的 offsetTop、offsetLeft 相同),其用法類似 offset (),但它只能作為 getter,無法設定值,從指定元素開始往上尋找,找到第一個 position 為 relative 或 absolute 為定位來做計算,如果都沒有找到,會以視窗左上角為偏移量(沒有設定 top、bottom、left、right 偏移量,照元素正常流向的推擠也算偏移),返回物件包含兩個屬性:top 和 left,此方法只能對可見元素有效。

.position()

$('.box').position().left
$('.box').position().top

offsetParent()

獲取被定位的最近祖先元素對象,每個元素都有個 offsetParent 屬性,用來指定元素的位置是相對於誰。已定位的元素永遠都是他們子裔元素的 offsetParent,jQuery 只會把已定位的元素當作 offsetParent,而 jQuery 物件的 offsetParent () 方法則會把每個元素對應至最接近它的已定位祖(ancestor)元素,或最後是 body 元素。

捲軸偏移量

scrollTop () 與 scrollLeft ()

可查詢元素在捲軸(scrollbar)的偏移量,或設定元素在捲軸的偏移量(px)。可用於 Window 物件,也可用於文件元素,而在 document 上呼叫時,它會設定內含該文件的 window 的捲動軸位置,與 window 相同,兩者都可以取得整個文件的捲動值。如果用在 $(‘div’) 等區塊元素,則可取得內嵌捲動框的捲動值。有別於其他 setters,你不能傳入一個函式給 scrollTop () 或 scrollLeft ()。scrollTop () 為元素距離捲軸最上方起始點的垂直偏移量,scrollLeft () 為元素距離捲軸最左側起始點的水平偏移量。如果滾動條位於最頂部,或者元素不可滾動,則此數字為 0。

scrollTop () 是以 viewport 最頂端為一條基準線,捲軸往下拉動 100px,則表示內容往上移動 100px。相同的概念可以應用到 JavaScript 的 pageYOffset(scrollY)。

.scrollTop()
.scrollTop(value)

$(window).on('scroll', function () {
console.log($(window).scrollTop())
})

scrollTop () 與 scrollLeft () 是用 JavaScript 的 pageXOffset、pageYOffset 實作,pageXOffset、pageYOffst 是 scrollX、scrollY 的別名,在跨瀏覽器兼容,應該使用 pageXOffset、pageYOffst。

捲軸捲到某位置出現

// 移動到頁尾卷軸需要的距離 = 頁尾到頂部的距離 - 視窗的高度(一開始的高度卷軸不需要移動)
let endZone = $('#footer').offset().top - $window.height()
$(window).on('scroll', function () {
// 移動到頁尾卷軸需要的距離 小於 當前捲軸移動的距離
if (endZone < $window.scrollTop()) {
console.log(`endZone:${endZone}`)
$('#ad').animate({ right: '0' }, 250)
} else {
$('#ad').stop(true).animate({ right: '-360px' }, 250)
}
})