Hiểu về offsetWidth, clientWidth, scrollWidth và -Height, tương ứng


385

Có một số câu hỏi trên StackOverflow liên quan đến offsetWidth / clientWidth / scrollWidth (và -Height, tương ứng), nhưng không có câu trả lời nào giải thích toàn diện về những giá trị đó là gì.

Ngoài ra, có một số nguồn trên web cung cấp thông tin khó hiểu hoặc không chính xác.

Bạn có thể đưa ra một lời giải thích đầy đủ bao gồm một số gợi ý trực quan? Ngoài ra, làm thế nào những giá trị đó có thể được sử dụng để tính chiều rộng thanh cuộn?

Câu trả lời:


869

Mô hình hộp CSS khá phức tạp, đặc biệt khi nói đến nội dung cuộn. Mặc dù trình duyệt sử dụng các giá trị từ CSS của bạn để vẽ các hộp, việc xác định tất cả các kích thước bằng cách sử dụng JS không đơn giản nếu bạn chỉ có CSS.

Đó là lý do tại sao mỗi phần tử có sáu đặc tính DOM thuận tiện cho bạn: offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidthscrollHeight. Đây là các thuộc tính chỉ đọc đại diện cho bố cục hình ảnh hiện tại và tất cả chúng là các số nguyên (do đó có thể bị lỗi làm tròn).

Chúng ta hãy đi qua chúng một cách chi tiết:

  • offsetWidth, offsetHeight: Kích thước của hộp trực quan bao gồm tất cả các đường viền. Có thể được tính bằng cách thêm width/ heightvà paddings và viền, nếu phần tử códisplay: block
  • clientWidth, clientHeight: Phần trực quan của nội dung hộp, không bao gồm viền hoặc thanh cuộn, nhưng bao gồm phần đệm. Không thể tính trực tiếp từ CSS, tùy thuộc vào kích thước thanh cuộn của hệ thống.
  • scrollWidth, scrollHeight: Kích thước của tất cả nội dung của hộp, bao gồm các phần hiện đang bị ẩn bên ngoài khu vực cuộn. Không thể được tính trực tiếp từ CSS, tùy thuộc vào nội dung.

Mô hình hộp CSS2

Dùng thử: jsFiddle


offsetWidthtính đến chiều rộng của thanh cuộn, chúng ta có thể sử dụng nó để tính chiều rộng của thanh cuộn thông qua công thức

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

Thật không may, chúng tôi có thể gặp lỗi làm tròn, vì offsetWidthclientWidthluôn là số nguyên, trong khi kích thước thực tế có thể là phân số với các mức thu phóng khác 1.

Lưu ý rằng

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

không không làm việc đáng tin cậy trong Chrome, vì lợi nhuận Chrome widthvới thanh cuộn đã khấu trừ. (Ngoài ra, Chrome hiển thị paddingBottom ở cuối nội dung cuộn, trong khi các trình duyệt khác thì không)


27
Đối với những người tìm kiếm độ chi tiết mịn hơn số nguyên, hãy sử dụng element.getBoundingClientRect()(xem ghi chú tại developer.mozilla.org/en-US/docs/Web/API/Euity.clientWidth )
Anson Kao

1
Lưu ý rằng tùy thuộc vào bố cục của bạn, scrollWidth và scrollHeight có thể thực sự hữu ích để có được kích thước của các phần tử giả :: trước và :: sau.
David

Ngoài ra, sẽ rất hữu ích khi giải thích làm thế nào những thứ đó liên quan đến naturalWidthnaturalHeight
YakovL

tại sao scrollHeightbao gồm padding-bottomnhưng scrollWidthkhông bao gồmpadding-right
JunGor

clientWidthcho document.documentElement.clientWidthlà khác nhau vì nó dường như bao gồm padding, bordersmargin
Drenai

50

Tôi đã tạo một phiên bản toàn diện và sạch sẽ hơn mà một số người có thể thấy hữu ích cho việc nhớ tên nào tương ứng với giá trị nào. Tôi đã sử dụng mã màu và nhãn của Chrome Dev Tool được sắp xếp đối xứng để thu thập các tín hiệu tương tự nhanh hơn:

nhập mô tả hình ảnh ở đây

  • Lưu ý 1: clientLeftcũng bao gồm chiều rộng của thanh cuộn dọc nếu hướng của văn bản được đặt từ phải sang trái (vì thanh được hiển thị ở bên trái trong trường hợp đó)

  • Lưu ý 2: dòng ngoài cùng đại diện cho cha mẹ được định vị gần nhất (một phần tử có thuộc positiontính được đặt thành giá trị khác statichoặc initial). Do đó, nếu vùng chứa trực tiếp không phải là phần tử được định vị , thì dòng không đại diện cho vùng chứa đầu tiên trong cấu trúc phân cấp mà là phần tử khác cao hơn trong cấu trúc phân cấp. Nếu không tìm thấy vị trí cha mẹ, trình duyệt sẽ lấy htmlhoặc body phần tử làm tham chiếu


Hy vọng ai đó thấy nó hữu ích, chỉ 2 xu của tôi;)


30

Nếu bạn muốn sử dụng scrollWidth để có được những "REAL" CONTENT WIDTH / HEIGHT (như nội dung có thể lớn hơn css xác định chiều rộng / chiều cao-Box) các scrollWidth / Chiều cao là rất không đáng tin cậy như một số trình duyệt dường như "MOVE" các paddingRIGHT & paddingBOTTOM nếu nội dung là lớn. Sau đó, họ đặt các miếng đệm ở RIGHT / BOTTOM của "nội dung quá rộng / cao" (xem hình dưới đây).

==> Do đó, để có được WIDTH NỘI DUNG THỰC SỰ trong một số trình duyệt, bạn phải loại bỏ các phần đệm từ băng thông và trong một số trình duyệt, bạn chỉ phải trừ phần đệm LEFT.

Tôi đã tìm thấy một giải pháp cho điều này và muốn thêm nó như một bình luận, nhưng không được phép. Vì vậy, tôi đã chụp bức ảnh và làm cho nó rõ ràng hơn một chút về "phần đệm di chuyển" và "scrollWidth không đáng tin cậy". Trong KHU VỰC XANH, bạn tìm thấy giải pháp của tôi về cách có được NỘI DUNG "THỰC SỰ"!

Hy vọng điều này sẽ giúp mọi thứ rõ ràng hơn!

nhập mô tả hình ảnh ở đây


13

Có một bài viết hay về MDN giải thích lý thuyết đằng sau những khái niệm đó: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

Nó cũng giải thích sự khác biệt về khái niệm quan trọng giữa chiều rộng / chiều cao của ràng buộc so với offsetWidth / offsetHeight.

Sau đó, để chứng minh lý thuyết đúng hay sai, bạn cần một số bài kiểm tra. Đó là những gì tôi đã làm ở đây: https://github.com/lingtalfi/dimensions-chcoateet

Đó là thử nghiệm cho chrome53, ff49, safari9, edge13 và eg11.

Kết quả của các bài kiểm tra chứng minh rằng lý thuyết nói chung là đúng. Đối với các bài kiểm tra, tôi đã tạo ra 3 div chứa 10 đoạn lorem ipsum mỗi đoạn. Một số css đã được áp dụng cho họ:

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

Và đây là kết quả:

  • div1

    • offsetWidth: 530 (chrome53, ff49, safari9, edge13, eg11)
    • offsetHeight: 330 (chrome53, ff49, safari9, edge13, eg11)
    • bcr. thong: 530 (chrome53, ff49, safari9, edge13, eg11)
    • bcr.height: 330 (chrome53, ff49, safari9, edge13, eg11)

    • clientWidth: 505 (chrome53, ff49, safari9)

    • clientWidth: 508 (cạnh13)
    • clientWidth: 503 (tức là 11)
    • clientHeight: 320 (chrome53, ff49, safari9, edge13, eg11)

    • scrollWidth: 505 (chrome53, safari9, ff49)

    • scrollWidth: 508 (cạnh13)
    • scrollWidth: 503 (tức là 11)
    • cuộnHeight: 916 (chrome53, safari9)
    • cuộnHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, eg11)
  • div2

    • offsetWidth: 500 (chrome53, ff49, safari9, edge13, eg11)
    • offsetHeight: 300 (chrome53, ff49, safari9, edge13, eg11)
    • bcr. thong: 500 (chrome53, ff49, safari9, edge13, eg11)
    • bcr.height: 300 (chrome53, ff49, safari9)
    • bcr.height: 299.9999694824219 (cạnh13, tức là 11)
    • clientWidth: 475 (chrome53, ff49, safari9)
    • clientWidth: 478 (cạnh13)
    • clientWidth: 473 (tức là 11)
    • clientHeight: 290 (chrome53, ff49, safari9, edge13, eg11)

    • scrollWidth: 475 (chrome53, safari9, ff49)

    • scrollWidth: 478 (cạnh13)
    • scrollWidth: 473 (tức là 11)
    • cuộnHeight: 916 (chrome53, safari9)
    • cuộnHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, eg11)
  • div3

    • offsetWidth: 530 (chrome53, ff49, safari9, edge13, eg11)
    • offsetHeight: 330 (chrome53, ff49, safari9, edge13, eg11)
    • bcr. thong: 265 (chrome53, ff49, safari9, edge13, eg11)
    • bcr.height: 165 (chrome53, ff49, safari9, edge13, eg11)
    • clientWidth: 505 (chrome53, ff49, safari9)
    • clientWidth: 508 (cạnh13)
    • clientWidth: 503 (tức là 11)
    • clientHeight: 320 (chrome53, ff49, safari9, edge13, eg11)

    • scrollWidth: 505 (chrome53, safari9, ff49)

    • scrollWidth: 508 (cạnh13)
    • scrollWidth: 503 (tức là 11)
    • cuộnHeight: 916 (chrome53, safari9)
    • cuộnHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, eg11)

Vì vậy, ngoài giá trị chiều cao của ràng buộcClientRect (299.9999694824219 thay vì 300 dự kiến) ở cạnh13 và eg11, kết quả xác nhận rằng lý thuyết đằng sau điều này hoạt động.

Từ đó, đây là định nghĩa của tôi về những khái niệm đó:

  • offsetWidth / offsetHeight: kích thước của hộp viền bố trí
  • ràng buộcClientRect: kích thước của hộp viền kết xuất
  • clientWidth / clientHeight: kích thước của phần hiển thị của hộp đệm bố cục (không bao gồm các thanh cuộn)
  • scrollWidth / scrollHeight: kích thước của hộp đệm bố cục nếu nó không bị ràng buộc bởi các thanh cuộn

Lưu ý: chiều rộng của thanh cuộn dọc mặc định là 12px ở edge13, 15px ở chrome53, ff49 và safari9 và 17px trong eg11 (được thực hiện bằng các phép đo trong photoshop từ ảnh chụp màn hình và được chứng minh bằng kết quả của các thử nghiệm).

Tuy nhiên, trong một số trường hợp, có thể ứng dụng của bạn không sử dụng chiều rộng của thanh cuộn dọc mặc định.

Vì vậy, với các định nghĩa về các khái niệm đó, chiều rộng của thanh cuộn dọc phải bằng (trong mã giả):

  • kích thước bố cục: offsetWidth - clientWidth - (BorderLeftWidth + BorderRightWidth)

  • kích thước kết xuất: ràng buộcClientRect. thong - clientWidth - (BorderLeftWidth + BorderRightWidth)

Lưu ý, nếu bạn không hiểu bố cục so với kết xuất, vui lòng đọc bài viết mDN.

Ngoài ra, nếu bạn có một trình duyệt khác (hoặc nếu bạn muốn xem kết quả của các bài kiểm tra), bạn có thể xem trang thử nghiệm của tôi ở đây: http://codepen.io/lingtalfi/pen/BLdBdL

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.