offsetWidth, clientWidth, scrollWidth 및 -Height 각각 이해


385

OffsetWidth / clientWidth / scrollWidth (및 -Height)와 관련하여 StackOverflow에 대한 몇 가지 질문이 있지만 해당 값이 무엇인지에 대한 포괄적 인 설명은 없습니다.

또한 웹상에서 혼란 스럽거나 잘못된 정보를 제공하는 여러 출처가 있습니다.

시각적 힌트를 포함하여 완전한 설명을 제공 할 수 있습니까? 또한 이러한 값을 사용하여 스크롤 막대 너비를 계산할 수 있습니까?

답변:


868

CSS 상자 모델은 특히 내용 스크롤과 관련하여 다소 복잡합니다. 브라우저는 CSS의 값을 사용하여 상자를 그리지 만 CSS 만 있으면 JS를 사용하여 모든 차원을 결정하는 것이 간단하지 않습니다.

각 요소는 사용자의 편의를 위해 여섯 개 DOM의 속성이 왜 그 : offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidthscrollHeight. 현재 시각적 레이아웃을 나타내는 읽기 전용 특성이며 모두 정수입니다 (따라서 반올림 오류가 발생할 수 있음).

그것들을 자세히 살펴 봅시다 :

  • offsetWidth, offsetHeight: 모든 테두리를 표시하는 시각적 상자의 크기입니다. 요소에 width/ height및 패딩 및 테두리 를 추가하여 계산할 수 있습니다.display: block
  • clientWidth, clientHeight: 테두리 나 스크롤 막대를 포함하지 않고 패딩을 포함하는 상자 내용의 시각적 부분. CSS에서 직접 계산할 수 없으며 시스템의 스크롤 막대 크기에 따라 다릅니다.
  • scrollWidth, scrollHeight: 현재 스크롤 영역 밖에 숨겨져있는 부분을 포함하여 모든 상자 내용의 크기입니다. CSS에서 직접 계산할 수 없으며 내용에 따라 다릅니다.

CSS2 박스 모델

사용해보십시오 : jsFiddle


이후 offsetWidth고려 스크롤바 폭을 얻어, 우리는 수식 통해 스크롤 바의 폭을 계산하기 위해 사용할 수있다

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

이후 불행하게도, 우리는 오류를 반올림 얻을 수 offsetWidthclientWidth항상 정수의 실제 크기가 1이 아닌 다른 줌 레벨 분수 될 수 있지만,.

이 점에 유의하십시오

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

Chrome에서 스크롤바를 이미 빼고 반환하므로 Chrome에서 안정적으로 작동 하지 않습니다width . 또한 Chrome은 paddingBottom을 스크롤 내용의 맨 아래로 렌더링하지만 다른 브라우저는 그렇지 않습니다.


27
정수보다 세분화 된 기능을 원하는 사용자는 element.getBoundingClientRect()( developer.mozilla.org/en-US/docs/Web/API/Element.clientWidth 참고 )
Anson Kao

1
레이아웃에 따라 scrollWidth 및 scrollHeight는 의사 요소의 크기를 :: before 및 :: after로 얻는 데 실제로 유용 할 수 있습니다.
David

또한, 사람들이 관련 할 방법을 설명하는 것이 유용 할 것입니다 naturalWidthnaturalHeight
YakovL

scrollHeight포함 padding-bottom하지만 포함 scrollWidth하지 않는 이유padding-right
JunGor

clientWidth대한이 document.documentElement.clientWidth가를 포함 보인다 다른 padding, borders그리고margin
Drenai

49

어떤 사람들은 어떤 이름이 어떤 가치에 해당하는지 기억하는 데 유용 할 수있는 더 포괄적이고 더 깨끗한 버전을 만들었습니다. Chrome Dev Tool의 색상 코드를 사용했으며 라벨을 대칭으로 구성하여 유추를 더 빨리 선택했습니다.

여기에 이미지 설명을 입력하십시오

  • 참고 1 : clientLeft텍스트 방향이 오른쪽에서 왼쪽으로 설정된 경우 세로 스크롤 막대의 너비도 포함합니다 (이 경우 막대가 왼쪽에 표시되므로).

  • 주 2 : 최 외곽 라인에 가장 가까운 대표 위치 부모 (그 요소 position속성보다는 다른 값으로 설정되어 static이상 initial). 따라서 직접 컨테이너가 배치 된 요소가 아닌 경우 선은 계층 구조에서 첫 번째 컨테이너가 아니라 계층 구조에서 더 높은 다른 요소를 나타냅니다. 배치 된 상위를 찾지 못하면 브라우저는 html또는 body 요소를 참조로 사용합니다.


누군가가 유용하다고 생각하기를 바랍니다. 내 2 센트;)


30

scrollWidth를 사용하여 "실제" 컨텐츠 너비 / 높이 를 얻으려면 (CSS 정의 너비 / 높이 상자보다 내용이 더 클 수 있으므로) scrollWidth / Height는 일부 브라우저가 패딩 을 "이동"하는 것처럼 매우 신뢰할 수 없습니다 & paddingBOTTOM 내용이 큰 경우. 그런 다음 패딩을 "너무 넓고 / 높은 콘텐츠"의 오른쪽 / 아래에 배치합니다 (아래 그림 참조).

==> 따라서 일부 브라우저에서 실제 콘텐츠 너비를 얻으려면 스크롤 너비에서 두 패딩을 모두 빼야하고 일부 브라우저에서는 왼쪽 패딩 만 빼면됩니다.

나는 이것에 대한 해결책을 찾았고 이것을 주석으로 추가하고 싶었지만 허용되지 않았다. 그래서 나는 "움직이는 패딩"과 "신뢰할 수없는 scrollWidth"와 관련하여 사진을 찍어 조금 더 명확하게 만들었습니다. BLUE AREA에서 "REAL"CONTENT WIDTH를 얻는 방법에 대한 솔루션을 찾으십시오!

이것이 더 명확 해 지길 바랍니다.

여기에 이미지 설명을 입력하십시오


13

MDN에 대한 개념에 대한 이론을 설명하는 좋은 기사가 있습니다. https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

또한 boundingClientRect의 너비 / 높이와 offsetWidth / offsetHeight의 중요한 개념적 차이점에 대해 설명합니다.

그런 다음 이론의 옳고 그름을 입증하려면 몇 가지 테스트가 필요합니다. 그것이 내가 여기서 한 일입니다 : https://github.com/lingtalfi/dimensions-cheatsheet

chrome53, ff49, safari9, edge13 및 ie11을 테스트 중입니다.

테스트 결과는 이론이 일반적으로 옳다는 것을 증명합니다. 테스트를 위해 10 개의 lorem ipsum 단락을 포함하는 3 개의 div를 만들었습니다. 일부 CSS가 그들에게 적용되었습니다.

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

결과는 다음과 같습니다.

  • div1

    • 오프셋 너비 : 530 (chrome53, ff49, safari9, edge13, ie11)
    • 오프셋 높이 : 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 (에지 13)
    • clientWidth : 503 (ie11)
    • clientHeight : 320 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth : 505 (chrome53, safari9, ff49)

    • scrollWidth : 508 (에지 13)
    • scrollWidth : 503 (ie11)
    • scrollHeight : 916 (chrome53, safari9)
    • scrollHeight : 954 (ff49)
    • scrollHeight : 922 (edge13, 즉 11)
  • div2

    • 오프셋 너비 : 500 (chrome53, ff49, safari9, edge13, ie11)
    • 오프셋 높이 : 300 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.width : 500 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height : 300 (chrome53, ff49, safari9)
    • bcr. 높이 : 299.9999694824219 (edge13, ie11)
    • clientWidth : 475 (chrome53, ff49, safari9)
    • clientWidth : 478 (에지 13)
    • clientWidth : 473 (ie11)
    • clientHeight : 290 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth : 475 (chrome53, safari9, ff49)

    • scrollWidth : 478 (에지 13)
    • scrollWidth : 473 (ie11)
    • scrollHeight : 916 (chrome53, safari9)
    • scrollHeight : 954 (ff49)
    • scrollHeight : 922 (edge13, 즉 11)
  • div3

    • 오프셋 너비 : 530 (chrome53, ff49, safari9, edge13, ie11)
    • 오프셋 높이 : 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 (에지 13)
    • clientWidth : 503 (ie11)
    • clientHeight : 320 (chrome53, ff49, safari9, edge13, ie11)

    • scrollWidth : 505 (chrome53, safari9, ff49)

    • scrollWidth : 508 (에지 13)
    • scrollWidth : 503 (ie11)
    • scrollHeight : 916 (chrome53, safari9)
    • scrollHeight : 954 (ff49)
    • scrollHeight : 922 (edge13, 즉 11)

따라서 edge13 및 ie11에서 boundingClientRect의 높이 값 (예상 300 대신 299.9999694824219 대신 300)을 제외하고이 결과의 이론이 작동 함을 확인했습니다.

여기에서 이러한 개념에 대한 나의 정의는 다음과 같습니다.

  • offsetWidth / offsetHeight : 레이아웃 테두리 상자의 크기
  • boundingClientRect : 렌더링 테두리 상자의 크기
  • clientWidth / clientHeight : 레이아웃 패딩 상자에서 보이는 부분의 크기 (스크롤 막대 제외)
  • scrollWidth / scrollHeight : 레이아웃 패딩 상자가 스크롤 막대로 제한되지 않은 경우 크기

참고 : 기본 세로 스크롤 막대의 너비는 edge13에서 12px, chrome53, ff49 및 safari9에서 15px, ie11에서 17px입니다 (스크린 샷에서 Photoshop에서 측정 한 결과, 테스트 결과에서 바로 확인 됨).

그러나 경우에 따라 앱에서 기본 세로 스크롤 막대의 너비를 사용하지 않을 수도 있습니다.

따라서 이러한 개념의 정의가 주어지면 세로 스크롤 막대의 너비는 (의사 코드)와 같아야합니다.

  • 레이아웃 차원 : offsetWidth-clientWidth-(borderLeftWidth + borderRightWidth)

  • 렌더링 차원 : boundingClientRect.width-clientWidth-(borderLeftWidth + borderRightWidth)

레이아웃 대 렌더링을 이해하지 못하면 mdn 기사를 읽으십시오.

또한 다른 브라우저가 있거나 테스트 결과를 보려면 http://codepen.io/lingtalfi/pen/BLdBdL 에서 내 테스트 페이지를 볼 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.