99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Javascript 元素大小和滾動

2023-02-17 10:54 更新

JavaScript 中有許多屬性可讓我們讀取有關(guān)元素寬度、高度和其他幾何特征的信息。

我們在 JavaScript 中移動或定位元素時,我們會經(jīng)常需要它們。

示例元素

作為演示屬性的示例元素,我們將使用下面給出的元素:

<div id="example">
  ...Text...
</div>
<style>
  #example {
    width: 300px;
    height: 200px;
    border: 25px solid #E8C48F;
    padding: 20px;
    overflow: auto;
  }
</style>

它有邊框(border),內(nèi)邊距(padding)和滾動(scrolling)等全套功能。但沒有外邊距(margin),因為它們不是元素本身的一部分,并且它們沒什么特殊的屬性。

這個元素看起來就像這樣:


你可以 在 sandbox 中打開這個文檔

注意滾動條

上圖演示了元素具有滾動條這種最復雜的情況。一些瀏覽器(并非全部)通過從內(nèi)容(上面標記為 “content width”)中獲取空間來為滾動條保留空間。

因此,如果沒有滾動條,內(nèi)容寬度將是 300 px,但是如果滾動條寬度是 16px(不同的設(shè)備和瀏覽器,滾動條的寬度可能有所不同),那么還剩下 300 - 16 = 284px,我們應該考慮到這一點。這就是為什么本章的例子總是假設(shè)有滾動條。如果沒有滾動條,一些計算會更簡單。

文本可能會溢出到 ?padding-bottom? 中

在我們的插圖中的 padding 中通常顯示為空,但是如果元素中有很多文本,并且溢出了,那么瀏覽器會在 padding-bottom 處顯示“溢出”文本,這是正?,F(xiàn)象。

幾何

這是帶有幾何屬性的整體圖片:


這些屬性的值在技術(shù)上講是數(shù)字,但這些數(shù)字其實是“像素(pixel)”,因此它們是像素測量值。

讓我們從元素外部開始探索屬性。

offsetParent,offsetLeft/Top

這些屬性很少使用,但它們?nèi)匀皇恰白钔饷妗钡膸缀螌傩?,所以我們將從它們開始。

offsetParent 是最接近的祖先(ancestor),在瀏覽器渲染期間,它被用于計算坐標。

最近的祖先為下列之一:

  1. CSS 定位的(?position? 為 ?absolute?、?relative?、fixed 或 ?sticky?),
  2. 或 ?<td>?,?<th>?,?<table>?,
  3. 或 ?<body>?。

屬性 offsetLeft/offsetTop 提供相對于 offsetParent 左上角的 x/y 坐標。

在下面這個例子中,內(nèi)部的 <div> 有 <main> 作為 offsetParent,并且 offsetLeft/offsetTop 讓它從左上角位移(180):

<main style="position: relative" id="main">
  <article>
    <div id="example" style="position: absolute; left: 180px; top: 180px">...</div>
  </article>
</main>
<script>
  alert(example.offsetParent.id); // main
  alert(example.offsetLeft); // 180(注意:這是一個數(shù)字,不是字符串 "180px")
  alert(example.offsetTop); // 180
</script>


有以下幾種情況下,offsetParent 的值為 null

  1. 對于未顯示的元素(?display:none? 或者不在文檔中)。
  2. 對于 ?<body>? 與 ?<html>?。
  3. 對于帶有 ?position:fixed? 的元素。

offsetWidth/Height

現(xiàn)在,讓我們繼續(xù)關(guān)注元素本身。

這兩個屬性是最簡單的。它們提供了元素的“外部” width/height?;蛘?,換句話說,它的完整大?。òㄟ吙颍?/p>


對于我們的示例元素:

  • ?offsetWidth = 390? —— 外部寬度(width),可以計算為內(nèi)部 CSS-width(?300px?)加上 padding(?2 * 20px?)和 border(?2 * 25px?)。
  • ?offsetHeight = 290? —— 外部高度(height)。

對于未顯示的元素,幾何屬性為 0/null

僅針對顯示的元素計算幾何屬性。

如果一個元素(或其任何祖先)具有 display:none 或不在文檔中,則所有幾何屬性均為零(或 offsetParent 為 null)。

例如,當我們創(chuàng)建了一個元素,但尚未將其插入文檔中,或者它(或它的祖先)具有 display:none 時,offsetParent 為 null,并且 offsetWidth 和 offsetHeight 為 0。

我們可以用它來檢查一個元素是否被隱藏,像這樣:

function isHidden(elem) {
  return !elem.offsetWidth && !elem.offsetHeight;
}

請注意,對于會展示在屏幕上,但大小為零的元素,它們的 isHidden 返回 true。

clientTop/Left

在元素內(nèi)部,我們有邊框(border)。

為了測量它們,可以使用 clientTop 和 clientLeft。

在我們的例子中:

  • ?clientLeft = 25? —— 左邊框?qū)挾?/li>
  • ?clientTop = 25? —— 上邊框?qū)挾?/li>


……但準確地說 —— 這些屬性不是邊框的 width/height,而是內(nèi)側(cè)與外側(cè)的相對坐標。

有什么區(qū)別?

當文檔從右到左顯示(操作系統(tǒng)為阿拉伯語或希伯來語)時,影響就顯現(xiàn)出來了。此時滾動條不在右邊,而是在左邊,此時 clientLeft 則包含了滾動條的寬度。

在這種情況下,clientLeft 的值將不是 25,而是加上滾動條的寬度 25 + 16 = 41。

這是希伯來語的例子:


clientWidth/Height

這些屬性提供了元素邊框內(nèi)區(qū)域的大小。

它們包括了 “content width” 和 “padding”,但不包括滾動條寬度(scrollbar):


在上圖中,我們首先考慮 clientHeight。

這里沒有水平滾動條,所以它恰好是 border 內(nèi)的總和:CSS-height 200px 加上頂部和底部的 padding(2 * 20px),總計 240px

現(xiàn)在 clientWidth —— 這里的 “content width” 不是 300px,而是 284px,因為被滾動條占用了 16px。所以加起來就是 284px 加上左側(cè)和右側(cè)的 padding,總計 324px。

如果這里沒有 padding,那么 clientWidth/Height 代表的就是內(nèi)容區(qū)域,即 border 和 scrollbar(如果有)內(nèi)的區(qū)域。


因此,當沒有 padding 時,我們可以使用 clientWidth/clientHeight 來獲取內(nèi)容區(qū)域的大小。

scrollWidth/Height

這些屬性就像 clientWidth/clientHeight,但它們還包括滾動出(隱藏)的部分:


在上圖中:

  • ?scrollHeight = 723? —— 是內(nèi)容區(qū)域的完整內(nèi)部高度,包括滾動出的部分。
  • ?scrollWidth = 324? —— 是完整的內(nèi)部寬度,這里我們沒有水平滾動,因此它等于 ?clientWidth?。

我們可以使用這些屬性將元素展開(expand)到整個 width/height。

像這樣:

// 將元素展開(expand)到完整的內(nèi)容高度
element.style.height = `${element.scrollHeight}px`;


scrollLeft/scrollTop

屬性 scrollLeft/scrollTop 是元素的隱藏、滾動部分的 width/height。

在下圖中,我們可以看到帶有垂直滾動塊的 scrollHeight 和 scrollTop。


換句話說,scrollTop 就是“已經(jīng)滾動了多少”。

?scrollLeft/scrollTop? 是可修改的

大多數(shù)幾何屬性是只讀的,但是 scrollLeft/scrollTop 是可修改的,并且瀏覽器會滾動該元素。

如果你點擊下面的元素,則會執(zhí)行代碼 elem.scrollTop += 10。這使得元素內(nèi)容向下滾動 10px。


將 scrollTop 設(shè)置為 0 或一個大的值,例如 1e9,將會使元素滾動到頂部/底部。

不要從 CSS 中獲取 width/height

我們剛剛介紹了 DOM 元素的幾何屬性,它們可用于獲得寬度、高度和計算距離。

但是,正如我們在 樣式和類 一章所知道的那樣,我們可以使用 getComputedStyle 來讀取 CSS-width 和 height。

那為什么不像這樣用 getComputedStyle 讀取元素的 width 呢?

let elem = document.body;

alert( getComputedStyle(elem).width ); // 顯示 elem 的 CSS width

為什么我們應該使用幾何屬性呢?這里有兩個原因:

  1. 首先,CSS ?width/height? 取決于另一個屬性:?box-sizing?,它定義了“什么是” CSS 寬度和高度。出于 CSS 的目的而對 ?box-sizing? 進行的更改可能會破壞此類 JavaScript 操作。
  2. 其次,CSS 的 ?width/height? 可能是 ?auto?,例如內(nèi)聯(lián)(inline)元素:
  3. <span id="elem">Hello!</span>
    
    <script>
      alert( getComputedStyle(elem).width ); // auto
    </script>

    從 CSS 的觀點來看,width:auto 是完全正常的,但在 JavaScript 中,我們需要一個確切的 px 大小,以便我們在計算中使用它。因此,這里的 CSS 寬度沒什么用。

還有另一個原因:滾動條。有時,在沒有滾動條的情況下代碼工作正常,當出現(xiàn)滾動條時,代碼就出現(xiàn)了 bug,因為在某些瀏覽器中,滾動條會占用內(nèi)容的空間。因此,可用于內(nèi)容的實際寬度小于 CSS 寬度。而 clientWidth/clientHeight 則會考慮到這一點。

……但是,使用 getComputedStyle(elem).width 時,情況就不同了。某些瀏覽器(例如 Chrome)返回的是實際內(nèi)部寬度減去滾動條寬度,而某些瀏覽器(例如 Firefox)返回的是 CSS 寬度(忽略了滾動條)。這種跨瀏覽器的差異是不使用 getComputedStyle 而依靠幾何屬性的原因。

如果你的瀏覽器保留了滾動條的空間(大多數(shù) Windows 中的瀏覽器),那么你可以在下面測試它。

https://zh.js.cx/article/size-and-scroll/cssWidthScroll/

帶有文本的元素具有 width:300px。

在桌面 Windows 操作系統(tǒng)上,F(xiàn)irefox、Chrome、Edge 都為滾動條保留了空間。但 Firefox 顯示的是 300px,而 Chrome 和 Edge 顯示較少。這是因為 Firefox 返回 CSS 寬度,其他瀏覽器返回“真實”寬度。

請注意,所描述的差異只是關(guān)于從 JavaScript 讀取的 getComputedStyle(...).width,而視覺上看,一切都是正確的。

總結(jié)

元素具有以下幾何屬性:

  • ?offsetParent? —— 是最接近的 CSS 定位的祖先,或者是 ?td?,?th?,?table?,?body?。
  • ?offsetLeft/offsetTop? —— 是相對于 ?offsetParent? 的左上角邊緣的坐標。
  • ?offsetWidth/offsetHeight? —— 元素的“外部” width/height,邊框(border)尺寸計算在內(nèi)。
  • ?clientLeft/clientTop? —— 從元素左上角外角到左上角內(nèi)角的距離。對于從左到右顯示內(nèi)容的操作系統(tǒng)來說,它們始終是左側(cè)/頂部 border 的寬度。而對于從右到左顯示內(nèi)容的操作系統(tǒng)來說,垂直滾動條在左邊,所以 ?clientLeft? 也包括滾動條的寬度。
  • ?clientWidth/clientHeight? —— 內(nèi)容的 width/height,包括 padding,但不包括滾動條(scrollbar)。
  • ?scrollWidth/scrollHeight? —— 內(nèi)容的 width/height,就像 ?clientWidth/clientHeight? 一樣,但還包括元素的滾動出的不可見的部分。
  • ?scrollLeft/scrollTop? —— 從元素的左上角開始,滾動出元素的上半部分的 width/height。

除了 scrollLeft/scrollTop 外,所有屬性都是只讀的。如果我們修改 scrollLeft/scrollTop,瀏覽器會滾動對應的元素。

任務


相對于底部滾動了多少?

重要程度: 5

elem.scrollTop 屬性是從頂部滾動出來的部分的大小。如何獲得底部滾動的大?。ㄎ覀兎Q其為 scrollBottom)?

編寫適用于任意 elem 的代碼。

P.S. 請檢查你的代碼:如果沒有滾動,或元素底部已經(jīng)完全滾動完成,那么它應該返回 0。


解決方案

解決方案:

let scrollBottom = elem.scrollHeight - elem.scrollTop - elem.clientHeight;

換句話說:(完全高度)減去(已滾出頂部的高度)減去(可見部分的高度)—— 得到的結(jié)果就是滾動出來的底部的部分。


滾動條的寬度是多少?

重要程度: 3

編寫代碼,返回標準滾動條寬度。

對于 Windows,它通常在 12px 和 20px 之間變化。如果瀏覽器沒有為其保留任何空間(滾動條以半透明的形式處于文本上面,也是可能發(fā)生的),那么它可能是 0px。

P.S. 該代碼應適用于任何 HTML 文檔,而不依賴于其內(nèi)容。


解決方案

為了獲得滾動條的寬度,我們可以創(chuàng)建一個帶有滾動條的元素,但是沒有邊框(border)和內(nèi)邊距(padding)。

然后,它的全寬度 offsetWidth 和內(nèi)部內(nèi)容寬度 clientWidth 之間的差值就是滾動條的寬度:

// 創(chuàng)建一個包含滾動條的 div
let div = document.createElement('div');

div.style.overflowY = 'scroll';
div.style.width = '50px';
div.style.height = '50px';

// 必須將其放入文檔(document)中,否則其大小將為 0
document.body.append(div);
let scrollWidth = div.offsetWidth - div.clientWidth;

div.remove();

alert(scrollWidth);

將小球置于區(qū)域(field)中心

重要程度: 5

源文件的效果如下:


區(qū)域(field)的中心坐標是多少?

計算它們,并將小球置于綠色的區(qū)域(field)中心:


  • 該元素應該通過 JavaScript 移動,而不是 CSS。
  • 該代碼應該適用于任何大小的球(?10?、?20?、?30? 像素)以及任意大小的區(qū)域(field),而不應該綁定到給定值。

P.S. 當然了,置于中心的操作通過 CSS 也可以完成,但是這里我們需要通過 JavaScript 完成。此外,當必須使用 JavaScript 時,我們可能會遇到其他話題以及更加復雜的情況,這里我們只是做一個“熱身”。

打開一個任務沙箱。


解決方案

球具有 position:absolute。這意味著它的 left/top 坐標是從最近的具有定位屬性的元素開始測量的,這個元素即 #field(因為它有 position:relative)。

坐標從場(field)的左上角內(nèi)側(cè)開始:


內(nèi)部的場(field)的 width/height 是 clientWidth/clientHeight。所以場(field)的中心坐標為 (clientWidth/2, clientHeight/2)。

……但是,如果我們將 ball.style.left/top 設(shè)置為這種值,那么在中心的會是球的左上邊緣,而不是整個球:

ball.style.left = Math.round(field.clientWidth / 2) + 'px';
ball.style.top = Math.round(field.clientHeight / 2) + 'px';

這是它將顯示出來的效果:


為了使球的中心與場(field)的中心重合,我們應該把球向左移動球?qū)挾鹊囊话耄⑾蛏弦苿忧蚋叨鹊囊话耄?

ball.style.left = Math.round(field.clientWidth / 2 - ball.offsetWidth / 2) + 'px';
ball.style.top = Math.round(field.clientHeight / 2 - ball.offsetHeight / 2) + 'px';

現(xiàn)在,球終于居中了。

注意:陷阱!

當 <img> 沒有 width/height 時,代碼將無法可靠地工作:

<img src="ball.png" id="ball">

當瀏覽器不知道圖片的 width/height(通過標簽 attribute 或 CSS)時,它會假定它們等于 0,直到圖片加載完成。

因此,在圖片加載完成之前,ball.offsetWidth 的值為 0。這會導致上面的代碼中會有錯誤的坐標。

在第一次加載完成后,瀏覽器通常會緩存該圖片,并在下一次加載時,瀏覽器會立即擁有該圖片的大小。但是在第一次加載時,ball.offsetWidth 的值為 0。

我們應該通過在 <img> 中添加 width/height 來解決這個問題:

<img src="ball.png" width="40" height="40" id="ball">

……或者在 CSS 中提供大小:

#ball {
  width: 40px;
  height: 40px;
}

使用沙箱打開解決方案。


CSS width 與 clientWidth 的不同點

重要程度: 5

getComputedStyle(elem).width 與 elem.clientWidth 之間有什么不同點?

指出至少三種不同點。當然越多越好。


解決方案

不同點:

  1. ?clientWidth? 值是數(shù)值,而 ?getComputedStyle(elem).width? 返回一個以 ?px? 作為后綴的字符串。
  2. ?getComputedStyle? 可能會返回非數(shù)值的 width,例如內(nèi)聯(lián)(inline)元素的 ?"auto"?。
  3. ?clientWidth? 是元素的內(nèi)部內(nèi)容區(qū)域加上 padding,而 CSS width(具有標準的 ?box-sizing?)是內(nèi)部內(nèi)容區(qū)域,不包括 padding。
  4. 如果有滾動條,并且瀏覽器為其保留了空間,那么某些瀏覽器會從 CSS width 中減去該空間(因為它不再可用于內(nèi)容),而有些則不會這樣做。?clientWidth? 屬性總是相同的:如果為滾動條保留了空間,那么將減去滾動條的大小。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號