OfsetWidth, clientWidth, scrollWidth ve -Height değerlerini anlama


385

StackOverflow ile ilgili olarak offsetWidth / clientWidth / scrollWidth (ve -Height, sırasıyla) ile ilgili birkaç soru vardır, ancak hiçbiri bu değerlerin ne olduğu hakkında kapsamlı bir açıklama yapmaz.

Ayrıca, web'de kafa karıştırıcı veya yanlış bilgi veren çeşitli kaynaklar vardır.

Bazı görsel ipuçları da dahil olmak üzere tam bir açıklama yapabilir misiniz? Ayrıca, bu değerler kaydırma çubuğu genişliklerini hesaplamak için nasıl kullanılabilir?

Yanıtlar:


869

CSS kutusu modeli, özellikle kaydırma içeriği söz konusu olduğunda oldukça karmaşıktır. Tarayıcı kutuları çizmek için CSS'nizdeki değerleri kullanırken, yalnızca CSS'niz varsa JS kullanarak tüm boyutları belirlemek basit değildir.

Her eleman kolaylık olması için altı DOM özelliklere sahip yüzden bu: offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidthve scrollHeight. Bunlar, geçerli görsel düzeni temsil eden salt okunur özniteliklerdir ve tümü tamsayılardır (bu nedenle muhtemelen yuvarlama hatalarına maruz kalırlar).

Onları ayrıntılı olarak inceleyelim:

  • offsetWidth, offsetHeight: Tüm kenarlıkları içeren görsel kutunun boyutu. Eleman varsa width/ heightve dolgu ve kenarlıklar eklenerek hesaplanabilirdisplay: block
  • clientWidth, clientHeight: Kutu içeriğinin kenarlıklar veya kaydırma çubukları hariç görsel kısmı, dolgu içerir. Doğrudan CSS'den hesaplanamaz, sistemin kaydırma çubuğu boyutuna bağlıdır.
  • scrollWidth, scrollHeight: Kaydırma alanının dışında gizlenmiş olan parçalar da dahil olmak üzere, kutunun tüm içeriğinin boyutu. İçeriğe bağlı olarak doğrudan CSS'den hesaplanamaz.

CSS2 Kutu Modeli

Deneyin: jsFiddle


Yana offsetWidthdikkate kaydırma çubuğu genişliği alır, aşağıdaki formül ile kaydırma çubuğu genişliğini hesaplamak için kullanabilir

scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth

Çünkü, maalesef hatalar yuvarlama alabilirsiniz offsetWidthve clientWidthher zaman tam sayılardır gerçek boyutları 1 dışında yakınlaştırma seviyeleri ile fraksiyonel olabilirken,.

Unutmayın ki

scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth

yok değil Krom döner beri, Chrome'da güvenilir çalışmak widthkaydırma çubuğu ile zaten çıkartılmış. (Ayrıca Chrome, paddingBottom'u kaydırma içeriğinin altına dönüştürürken diğer tarayıcılar oluşturmaz)


27
Tamsayılardan daha ince ayrıntı düzeyi isteyenler için şunu kullanın element.getBoundingClientRect()( developer.mozilla.org/en-US/docs/Web/API/Element.clientWidth adresindeki nota bakın )
Anson Kao

1
Düzeninize bağlı olarak, scrollWidth ve scrollHeight öğelerinin sahte öğelerinizin boyutunu :: before ve :: after almak için gerçekten yararlı olabileceğini unutmayın.
David

Ayrıca, bunların nasıl bir ilişki ile ilgili olduğunu açıklamak yararlı olacaktır naturalWidthvenaturalHeight
YakovL

neden scrollHeightiçerir padding-bottomancak scrollWidthiçermezpadding-right
JunGor

clientWidthiçin document.documentElement.clientWidtho dahil etmek göründüğü gibi farklıdır padding, bordersvemargin
Drenai

50

Bazı kişilerin hangi ismin hangi değere karşılık geldiğini hatırlamak için yararlı bulabileceği daha kapsamlı ve daha temiz bir sürüm oluşturdum. Chrome Dev Tool'un renk kodunu kullandım ve analojileri daha hızlı almak için etiketler simetrik olarak düzenlenmiş:

resim açıklamasını buraya girin

  • Not 1: clientLeftmetnin yönü sağdan sola olarak ayarlanmışsa dikey kaydırma çubuğunun genişliğini de içerir (bu durumda çubuk sola görüntülendiğinden)

  • Not 2: en dıştaki çizgi en yakın konumlandırılmış üst öğeyi ( positionözelliği staticveya değerinden farklı bir değere ayarlanmış bir öğe) temsil eder initial. Bu nedenle, doğrudan kap konumlandırılmış bir öğe değilse , satır hiyerarşideki ilk kapsayıcıyı değil, hiyerarşideki daha yüksek başka bir öğeyi temsil eder. Hayır ise konumlandırılmış üst bulunursa, tarayıcı alacak htmlveya body referans olarak eleman


Umarım biri faydalı bulur, sadece 2 sentim;)


30

Eğer almak için scrollWidth kullanmak istiyorsanız "GERÇEK" İÇERİK genişlik / yükseklik (içerik css tanımlı genişlik / yükseklik-kutusundan büyük olabilir gibi) scrollWidth / Yükseklik çok GÜVENİLMEZ olduğu bazı tarayıcı olarak paddingRIGHT "HAMLE" görünüyor & paddingBOTTOM, içerik büyükse. Daha sonra dolguları "çok geniş / yüksek içeriğin" SAĞ / ALTINA yerleştirirler (aşağıdaki resme bakın).

==> Bu nedenle, bazı tarayıcılarda GERÇEK İÇERİK GENİŞLİĞİNİ elde etmek için, kaydırma genişliğinden İKİ dolguyu soyutlamanız ve bazı tarayıcılarda yalnızca SOL Dolguyu soyutlamanız gerekir.

Bunun için bir çözüm buldum ve bunu bir yorum olarak eklemek istedim, ancak izin verilmedi. Bu yüzden resmi aldım ve "taşınmış paddings" ve "güvenilmez scrollWidth" açısından biraz daha net yaptım. MAVİ ALANDA "GERÇEK" İÇERİK GENİŞLİĞİNİ nasıl alacağınıza dair çözümümü bulacaksınız!

Umarım bu daha da netleşir!

resim açıklamasını buraya girin


13

MDN hakkında bu kavramların arkasındaki teoriyi açıklayan iyi bir makale var: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

Aynı zamanda sınırlamaClientRect'in genişliği / yüksekliği ile offsetWidth / offsetHeight arasındaki önemli kavramsal farklılıkları da açıklar.

Sonra, teoriyi doğru ya da yanlış kanıtlamak için bazı testlere ihtiyacınız var. Burada yaptığım şey: https://github.com/lingtalfi/dimensions-cheatsheet

Chrome53, ff49, safari9, edge13 ve ie11 için test yapıyor.

Testlerin sonuçları teorinin genellikle doğru olduğunu kanıtlar. Testler için, her birinde 10 lorem ipsum paragrafı içeren 3 div oluşturdum. Onlara bazı css uygulandı:

.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);
}

İşte sonuçlar:

  • div1

    • ofsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
    • ofsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.width: 530 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height: 330 (chrome53, ff49, safari9, edge13, ie11)

    • clientWidth: 505 (chrome53, ff49, safari9)

    • clientWidth: 508 (kenar13)
    • istemci Genişliği: 503 (ie11)
    • clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth: 505 (chrome53, safari9, ff49)

    • scrollWidth: 508 (kenar13)
    • kaydırma genişliği: 503 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (kenar13; yani11)
  • DIV2

    • ofsetWidth: 500 (chrome53, ff49, safari9, edge13, ie11)
    • ofsetHeight: 300 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.width: 500 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height: 300 (chrome53, ff49, safari9)
    • bcr.height: 299.9999694824219 (kenar13, ie11)
    • clientWidth: 475 (chrome53, ff49, safari9)
    • clientWidth: 478 (kenar13)
    • istemci Genişliği: 473 (ie11)
    • clientHeight: 290 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth: 475 (chrome53, safari9, ff49)

    • scrollWidth: 478 (kenar13)
    • scrollWidth: 473 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (kenar13; yani11)
  • DIV3

    • ofsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
    • ofsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.width: 265 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height: 165 (chrome53, ff49, safari9, edge13, ie11)
    • clientWidth: 505 (chrome53, ff49, safari9)
    • clientWidth: 508 (kenar13)
    • istemci Genişliği: 503 (ie11)
    • clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth: 505 (chrome53, safari9, ff49)

    • scrollWidth: 508 (kenar13)
    • kaydırma genişliği: 503 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (kenar13; yani11)

Dolayısıyla, edge13 ve ie11'deki boundingClientRect'in yükseklik değeri (beklenen 300 yerine 299.9999694824219) dışında, sonuçlar bunun arkasındaki teorinin çalıştığını doğrulamaktadır.

Oradan, bu kavramları tanımım:

  • offsetWidth / offsetHeight: düzen kenarlık kutusunun boyutları
  • boundingClientRect: işleme kenarlık kutusunun boyutları
  • clientWidth / clientHeight: düzen dolgu kutusunun görünür bölümünün boyutları (kaydırma çubukları hariç)
  • scrollWidth / scrollHeight: kaydırma çubukları tarafından kısıtlanmamışsa, düzen dolgu kutusunun boyutları

Not: varsayılan dikey kaydırma çubuğunun genişliği kenarlarda 12 piksel 13, krom53'te 15 piksel, ff49 ve safari9 ve ie11'de 17 pikseldir (ekran görüntülerinden photoshop'ta yapılan ölçümlerle yapılır ve testlerin sonuçlarıyla kanıtlanmıştır).

Ancak, bazı durumlarda, uygulamanız varsayılan dikey kaydırma çubuğunun genişliğini kullanmıyor olabilir.

Bu nedenle, bu kavramların tanımları göz önüne alındığında, dikey kaydırma çubuğunun genişliği eşit olmalıdır (sözde kodda):

  • düzen boyutu: offsetWidth - clientWidth - (borderLeftWidth + borderRightWidth)

  • oluşturma boyutu: boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)

Not, mizanpaj vs oluşturma anlamıyorsanız, lütfen mdn makalesini okuyun.

Ayrıca, başka bir tarayıcınız varsa (veya testlerin sonuçlarını kendiniz görmek istiyorsanız) test sayfamı burada görebilirsiniz: http://codepen.io/lingtalfi/pen/BLdBdL

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.