Velikost prvku a posouvání

Existuje mnoho vlastností JavaScriptu, které nám umožňují číst informace o šířce, výšce a dalších geometrických funkcích.

Často je potřebujeme při přesouvání nebo umisťování prvků v JavaScriptu.

Ukázkový prvek

Jako ukázkový prvek k demonstraci vlastností použijeme prvek uvedený níže:

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

Má ohraničení, výplň a rolování. Kompletní sada funkcí. Nejsou zde žádné okraje, protože nejsou součástí samotného prvku a neexistují pro ně žádné speciální vlastnosti.

Prvek vypadá takto:

Dokument můžete otevřít v karanténě.

Pozor na posuvník

Obrázek výše ukazuje nejsložitější případ, kdy má prvek posuvník. Některé prohlížeče (ne všechny) si pro něj rezervují místo tím, že jej převezmou z obsahu (výše označeného jako „šířka obsahu“).

Takže bez posuvníku by šířka obsahu byla 300px , ale pokud je posuvník 16px široký (šířka se může mezi zařízeními a prohlížeči lišit), pak pouze 300 - 16 = 284px zůstává a měli bychom to vzít v úvahu. Proto příklady z této kapitoly předpokládají, že existuje posuvník. Bez něj jsou některé výpočty jednodušší.

padding-bottom oblast může být vyplněna textem

Výplně jsou na našich ilustracích obvykle zobrazeny prázdné, ale pokud je v prvku mnoho textu a přetéká, prohlížeče zobrazí „přetékající“ text na padding-bottom , to je normální.

Geometrie

Zde je celkový obrázek s vlastnostmi geometrie:

Hodnoty těchto vlastností jsou technicky čísla, ale tato čísla jsou „pixelů“, takže se jedná o měření pixelů.

Začněme zkoumat vlastnosti počínaje vnějškem prvku.

offsetParent, offsetLeft/Top

Tyto vlastnosti jsou potřeba jen zřídka, ale přesto jsou to „nejvnější“ vlastnosti geometrie, takže začneme s nimi.

offsetParent je nejbližší předek, kterého prohlížeč používá pro výpočet souřadnic během vykreslování.

To je nejbližší předek, který je jedním z následujících:

  1. Umístění CSS (position je absolute , relative , fixed nebo sticky ), nebo
  2. <td> , <th> nebo <table> nebo
  3. <body> .

Vlastnosti offsetLeft/offsetTop zadejte souřadnice x/y vzhledem k offsetParent levém horním rohu.

V níže uvedeném příkladu vnitřní <div><main> jako offsetParent a offsetLeft/offsetTop posune z levého horního rohu (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 (note: a number, not a string "180px")
 alert(example.offsetTop); // 180
</script>

Existuje několik případů, kdy offsetParent je null :

  1. Pro nezobrazené prvky (display:none nebo není v dokumentu).
  2. Pro <body> a <html> .
  3. Pro prvky s position:fixed .

offsetWidth/Height

Nyní přejdeme k samotnému prvku.

Tyto dvě vlastnosti jsou nejjednodušší. Poskytují „vnější“ šířku/výšku prvku. Nebo jinými slovy, jeho plná velikost včetně okrajů.

Pro náš ukázkový prvek:

  • offsetWidth = 390 – vnější šířku lze vypočítat jako vnitřní šířku CSS (300px ) plus výplně (2 * 20px ) a ohraničení (2 * 25px ).
  • offsetHeight = 290 – vnější výška.
Vlastnosti geometrie jsou nulové/nulové pro prvky, které nejsou zobrazeny

Vlastnosti geometrie se počítají pouze pro zobrazené prvky.

Pokud má prvek (nebo kterýkoli z jeho předků) display:none nebo není v dokumentu, pak jsou všechny vlastnosti geometrie nulové (nebo null pro offsetParent ).

Například offsetParent je null a offsetWidth , offsetHeight jsou 0 když jsme vytvořili prvek, ale ještě jsme ho nevložili do dokumentu, nebo má (nebo jeho předchůdce) display:none .

Můžeme to použít ke kontrole, zda je prvek skrytý, takto:

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

Vezměte prosím na vědomí, že takový isHidden vrátí true pro prvky, které jsou na obrazovce, ale mají nulovou velikost.

klient nahoře/vlevo

Uvnitř prvku máme ohraničení.

K jejich měření existují vlastnosti clientTop a clientLeft .

V našem příkladu:

  • clientLeft = 25 – šířka levého okraje
  • clientTop = 25 – šířka horního okraje

…Ale abych byl přesný – tyto vlastnosti nejsou šířka/výška okraje, ale relativní souřadnice vnitřní strany od vnější strany.

Jaký je rozdíl?

Zviditelní se, když je dokument zprava doleva (operační systém je v arabštině nebo hebrejštině). Posuvník pak není vpravo, ale vlevo a pak clientLeft zahrnuje také šířku posuvníku.

V takovém případě clientLeft nebude 25 , ale s šířkou posuvníku 25 + 16 = 41 .

Zde je příklad v hebrejštině:

šířka/výška klienta

Tyto vlastnosti poskytují velikost oblasti uvnitř hranic prvku.

Zahrnují šířku obsahu spolu s odsazením, ale bez posuvníku:

Na obrázku výše nejprve uvažujme clientHeight .

Neexistuje žádný vodorovný posuvník, takže je to přesně součet toho, co je uvnitř ohraničení:CSS-height 200px plus horní a spodní vycpávky (2 * 20px ) celkem 240px .

Nyní clientWidth – zde není šířka obsahu 300px , ale 284px , protože 16px jsou obsazeny posuvníkem. Součet je tedy 284px plus levé a pravé vycpávky, celkem 324px .

Pokud nejsou žádné výplně, pak clientWidth/Height je přesně oblast obsahu, uvnitř ohraničení a posuvníku (pokud existuje).

Takže když neexistuje žádná výplň, můžeme použít clientWidth/clientHeight získat velikost oblasti obsahu.

šířka/výška posuvníku

Tyto vlastnosti jsou jako clientWidth/clientHeight , ale zahrnují také odrolované (skryté) části:

Na obrázku výše:

  • scrollHeight = 723 – je plná vnitřní výška oblasti obsahu včetně vysunutých částí.
  • scrollWidth = 324 – je plná vnitřní šířka, zde nemáme žádné vodorovné posouvání, takže se rovná clientWidth .

Tyto vlastnosti můžeme použít k rozšíření prvku do šířky na jeho plnou šířku/výšku.

Takhle:

// expand the element to the full content height
element.style.height = `${element.scrollHeight}px`;

Kliknutím na tlačítko prvek rozbalíte:

text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text

scrollLeft/scrollTop

Vlastnosti scrollLeft/scrollTop jsou šířka/výška skryté, vysunuté části prvku.

Na obrázku níže vidíme scrollHeight a scrollTop pro blok se svislým posouváním.

Jinými slovy scrollTop je „o kolik je posunuto nahoru“.

scrollLeft/scrollTop lze upravit

Většina vlastností geometrie zde je pouze pro čtení, ale scrollLeft/scrollTop lze změnit a prohlížeč bude prvek posouvat.

Pokud kliknete na prvek níže, kód elem.scrollTop += 10 provádí. Tím se obsah prvku posune na 10px dolů.

Klikněte

1
2
3
4
5
6
7
8
9

Nastavení scrollTop na 0 nebo velkou hodnotu, například 1e9 způsobí, že se prvek posune úplně nahoru/dolů.

Neberte šířku/výšku z CSS

Právě jsme probrali geometrické vlastnosti prvků DOM, které lze použít k získání šířky, výšky a výpočtu vzdáleností.

Ale jak víme z kapitoly Styly a třídy, CSS-height and width můžeme číst pomocí getComputedStyle .

Proč tedy nečíst šířku prvku pomocí getComputedStyle , takhle?

let elem = document.body;

alert( getComputedStyle(elem).width ); // show CSS width for elem

Proč bychom místo toho měli používat vlastnosti geometrie? Existují dva důvody:

  1. Nejprve CSS width/height závisí na jiné vlastnosti:box-sizing který definuje šířku a výšku CSS „co je“. Změna v box-sizing pro účely CSS může takový JavaScript porušit.

  2. Za druhé, CSS width/height může být auto , například pro vložený prvek:

    <span id="elem">Hello!</span>
    
    <script>
     alert( getComputedStyle(elem).width ); // auto
    </script>

    Z hlediska CSS width:auto je naprosto normální, ale v JavaScriptu potřebujeme přesnou velikost v px které můžeme použít při výpočtech. Takže zde je šířka CSS k ničemu.

A je tu ještě jeden důvod:posuvník. Někdy se kód, který funguje bez posuvníku, stává chybným, protože posuvník v některých prohlížečích zabírá místo obsahu. Skutečná šířka dostupná pro obsah je tedy menší než šířka CSS. A clientWidth/clientHeight vzít to v úvahu.

…Ale s getComputedStyle(elem).width situace je jiná. Některé prohlížeče (např. Chrome) vracejí skutečnou vnitřní šířku mínus posuvník a některé z nich (např. Firefox) – šířku CSS (posuvník ignorují). Takové rozdíly mezi prohlížeči jsou důvodem, proč nepoužívat getComputedStyle , ale spíše spoléhat na vlastnosti geometrie.

Pokud si váš prohlížeč vyhrazuje místo pro posuvník (většina prohlížečů pro Windows ho má), můžete jej otestovat níže.

Prvek s textem má CSS width:300px .

Na stolním operačním systému Windows, Firefox, Chrome, Edge všechny rezervují prostor pro posuvník. Firefox ale zobrazuje 300px , zatímco Chrome a Edge zobrazují méně. Je to proto, že Firefox vrací šířku CSS a ostatní prohlížeče vrací „skutečnou“ šířku.

Upozorňujeme, že popsaný rozdíl se týká pouze čtení getComputedStyle(...).width z JavaScriptu, vizuálně je vše v pořádku.

Shrnutí

Prvky mají následující vlastnosti geometrie:

  • offsetParent – je nejbližší umístěný předek nebo td , th , table , body .
  • offsetLeft/offsetTop – souřadnice vzhledem k levému hornímu okraji offsetParent .
  • offsetWidth/offsetHeight – „vnější“ šířka/výška prvku včetně ohraničení.
  • clientLeft/clientTop – vzdálenosti od levého horního vnějšího rohu k levému hornímu vnitřnímu rohu (obsah + výplň). U OS zleva doprava jsou to vždy šířky levého/horního okraje. U OS se zprava doleva je svislý posuvník vlevo, takže clientLeft zahrnuje i jeho šířku.
  • clientWidth/clientHeight – šířka/výška obsahu včetně odsazení, ale bez posuvníku.
  • scrollWidth/scrollHeight – šířka/výška obsahu, stejně jako clientWidth/clientHeight , ale také zahrnují odrolovanou, neviditelnou část prvku.
  • scrollLeft/scrollTop – šířka/výška odsunuté horní části prvku, počínaje jeho levým horním rohem.

Všechny vlastnosti jsou pouze pro čtení kromě scrollLeft/scrollTop které při změně posouvají prvek v prohlížeči.