Zrozumienie odpowiednio offsetWidth, clientWidth, scrollWidth i-Height
W Stoskoverflow jest kilka pytań dotyczących offsetWidth/clientWidth/scrollWidth (oraz-Height, odpowiednio), ale żadne z nich nie wyjaśnia wyczerpująco, czym są te wartości.
Ponadto, istnieje kilka źródeł w Internecie podając mylące lub nieprawidłowe informacje.
Czy możesz podać pełne wyjaśnienie, w tym wskazówki wizualne? W jaki sposób można również wykorzystać te wartości do obliczania szerokości paska przewijania?
4 answers
Model pudełkowy CSS jest dość skomplikowany, szczególnie jeśli chodzi o przewijanie zawartości. Podczas gdy przeglądarka używa wartości z twojego CSS do rysowania pól, określanie wszystkich wymiarów za pomocą JS nie jest proste, jeśli masz tylko CSS.
Dlatego każdy element ma sześć właściwości DOM dla Twojej wygody: offsetWidth
, offsetHeight
, clientWidth
, clientHeight
, scrollWidth
i scrollHeight
. Są to atrybuty tylko do odczytu reprezentujące aktualny układ wizualny, a wszystkie z nich są liczbami całkowitymi (Tak więc prawdopodobnie z powodu błędów zaokrąglania).
Przejrzyjmy je szczegółowo:
-
offsetWidth
,offsetHeight
: wielkość pola wizualnego obejmującego wszystkie granice. Można obliczyć dodającwidth
/height
oraz paddings i borders, jeśli element madisplay: block
-
clientWidth
,clientHeight
: wizualna część zawartości pudełka, nie obejmuje obramowań ani pasków przewijania, ale zawiera wypełnienia . Nie można obliczyć bezpośrednio z CSS, zależy od rozmiaru paska przewijania systemu. -
scrollWidth
,scrollHeight
: Rozmiar całej zawartości pudełka, w tym części, które są obecnie ukryte poza obszarem przewijania. Nie można obliczyć bezpośrednio z CSS, zależy od zawartości.
Wypróbuj: jsFiddle
Ponieważ offsetWidth
uwzględnia Szerokość paska przewijania, możemy użyć go do obliczenia szerokości paska przewijania za pomocą wzoru
scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth
Niestety, mogą pojawić się błędy zaokrąglania, ponieważ offsetWidth
i clientWidth
są zawsze liczby całkowite, podczas gdy rzeczywiste rozmiary mogą być ułamkowe z poziomami powiększenia innymi niż 1.
Zauważ, że to
scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth
Czy Nie działa niezawodnie w Chrome, ponieważ Chrome zwraca width
z odjętym paskiem przewijania. Chrome wyświetla również paddingBottom na dole zawartości przewijania, podczas gdy inne przeglądarki tego nie robią.]}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-17 08:23:43
Jeśli chcesz użyć scrollWidth, aby uzyskać "REAL" CONTENT WIDTH / HEIGHT (ponieważ zawartość może być większa niż okno width/height zdefiniowane przez css) scrollWidth / Height jest bardzo zawodne Jak niektóre przeglądarki wydają się "przenieść" paddingRIGHT & paddingBOTTOM jeśli zawartość jest duża. Następnie umieszczają podkładki po prawej / na dole " zbyt szerokiej / wysokiej zawartości "(patrz zdjęcie poniżej).
==> Dlatego, aby uzyskać rzeczywistą szerokość zawartości w niektórych przeglądarkach masz aby odjąć oba paddingi od przewijania, a w niektórych przeglądarkach wystarczy odjąć lewe Padding.
Znalazłem na to rozwiązanie i chciałem dodać to jako komentarz, ale nie było dozwolone. Zrobiłem więc zdjęcie i uczyniłem je nieco wyraźniejszym w odniesieniu do" przesuniętych paddingów "i"zawodnego przewijania". W niebieskim obszarze znajdziesz moje rozwiązanie, jak uzyskać "prawdziwą" szerokość treści!
Hope this helps to make things even jaśniej!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 13:07:56
Stworzyłem bardziej kompleksową i czystszą wersję, która może być przydatna dla niektórych osób do zapamiętywania, która nazwa odpowiada jakiej wartości. Użyłem kodu kolorów Chrome Dev Tool i etykiety są zorganizowane symetrycznie, aby szybciej odbierać analogie: {]}
-
Uwaga 1:
clientLeft
obejmuje również szerokość pionowego przewijania bar, jeśli Kierunek tekstu jest ustawiony na prawo-do-lewej (ponieważ pasek jest wyświetlany po lewej stronie w tym case) -
Uwaga 2: najbardziej wysunięta linia reprezentuje najbliższą pozycjonowanie rodzic (element, którego właściwość
position
jest ustawiona na wartość inną niżstatic
lubinitial
). Tak więc, jeśli bezpośredni kontener nie jest pozycjonowanie element, wtedy linia nie przedstawia pierwszego kontenera w hierarchii, ale kolejny element wyżej w hierarchii. Jeśli nie pozycjonowanie rodzica znajduje się, przeglądarka zajmiehtml
lubbody
element jako odniesienie
Mam nadzieję, że komuś się przyda, tylko moje 2 grosze ;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-30 03:18:25
Jest dobry artykuł na temat MDN, który wyjaśnia teorię stojącą za tymi pojęciami: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
Wyjaśnia również istotne różnice koncepcyjne między szerokością/wysokością boundingClientRect a offsetWidth/offsetHeight.
Następnie, aby udowodnić teorię dobrze lub źle, potrzebujesz testów. To właśnie zrobiłem.: https://github.com/lingtalfi/dimensions-cheatsheet
Testuje chrome53, ff49, safari9, edge13 i ie11.Wyniki testów dowodzą, że teoria jest ogólnie słuszna. Na potrzeby testów stworzyłem 3 divy zawierające po 10 akapitów lorem ipsum każdy. Niektóre css zostały do nich zastosowane:
.div1{
width: 500px;
height: 300px;
padding: 10px;
border: 5px solid black;
overflow: auto;
}
.div2{
width: 500px;
height: 300px;
padding: 10px;
border: 5px solid black;
box-sizing: border-box;
overflow: auto;
}
.div3{
width: 500px;
height: 300px;
padding: 10px;
border: 5px solid black;
overflow: auto;
transform: scale(0.5);
}
A oto wyniki:
-
Div1
- offsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
- offsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
- bcr.szerokość: 530 (chrome53, ff49, safari9, edge13, ie11)
-
Bcr.Wysokość: 330 (chrome53, ff49, safari9, edge13, ie11)
-
ClientWidth: 505 (chrome53, ff49, safari9)
- clientWidth: 508 (edge13)
- clientWidth: 503 (ie11)
-
ClientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)
-
ScrollWidth: 505 (chrome53, safari9, ff49)
- scrollWidth: 508 (edge13)
- scrollWidth: 503 (ie11)
- scrollHeight: 916 (chrome53, safari9)
- scrollHeight: 954 (ff49)
- scrollHeight: 922 (edge13, ie11)
-
Div2
- offsetWidth: 500 (chrome53, ff49, safari9, edge13, ie11)
- offsetHeight: 300 (chrome53, ff49, safari9, edge13, ie11)
- bcr.szerokość: 500 (chrome53, ff49, safari9, edge13, ie11)
- bcr.wysokość: 300 (chrome53, ff49, safari9)
- bcr.wysokość: 299.9999694824219 (edge13, ie11)
- clientWidth: 475 (chrome53, ff49, safari9)
- clientWidth: 478 (edge13)
- clientWidth: 473 (ie11)
-
ClientHeight: 290 (chrome53, ff49, safari9, edge13, ie11)
-
ScrollWidth: 475 (chrome53, safari9, ff49)
- scrollWidth: 478 (edge13)
- scrollWidth: 473 (ie11)
- scrollHeight: 916 (chrome53, safari9)
- scrollHeight: 954 (ff49)
- scrollHeight: 922 (edge13, ie11)
-
Div3
- offsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
- offsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
- bcr.szerokość: 265 (chrome53, ff49, safari9, edge13, ie11)
- bcr.wysokość: 165 (chrome53, ff49, safari9, edge13, ie11)
- clientWidth: 505 (chrome53, ff49, safari9)
- clientWidth: 508 (edge13)
- clientWidth: 503 (ie11)
-
ClientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)
-
ScrollWidth: 505 (chrome53, safari9, ff49)
- scrollWidth: 508 (edge13)
- scrollWidth: 503 (ie11)
- scrollHeight: 916 (chrome53, safari9)
- scrollHeight: 954 (ff49)
- scrollHeight: 922 (edge13, ie11)
Więc, oprócz wartości wysokości boundingClientRect (299.9999694824219 zamiast oczekiwanego 300) W edge13 i ie11, wyniki potwierdzają, że teoria za tym działa.
Stąd moja definicja tych pojęć:- offsetWidth/ offsetHeight: wymiary ramki układu
- boundingClientRect: wymiary ramki renderującej
- clientWidth/clientHeight: wymiary widocznej części pola wypełnienia układu (z wyłączeniem pasków przewijania)
- scrollWidth / scrollHeight: wymiary pola wypełnienia układu, jeśli nie było ograniczone paskami przewijania
Uwaga: domyślna szerokość pionowego paska przewijania wynosi 12px w edge13, 15px w chrome53, ff49 i safari9 oraz 17px w ie11(wykonane przez pomiary w Photoshopie z zrzutów ekranu i potwierdzone wynikami testów).
Jednak w niektórych przypadkach może Twoja aplikacja nie używa domyślnej szerokości pionowego paska przewijania.
Więc, biorąc pod uwagę definicje tych pojęć, szerokość pionowego paska przewijania powinna być równa (w pseudo kod): {]}
-
Wymiary układu: offsetWidth-clientWidth - (borderLeftWidth + borderRightWidth)
-
Wymiar renderowania: boundingClientRect.szerokość-clientWidth - (borderLeftWidth + borderRightWidth)
Uwaga, Jeśli nie rozumiesz układu i renderowania, przeczytaj artykuł mdn.
Również, jeśli masz inną przeglądarkę (lub jeśli chcesz zobaczyć wyniki testów dla siebie), możesz zobaczyć moją stronę testową tutaj: http://codepen.io/lingtalfi/pen/BLdBdL
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-05 12:58:56