OffsetWidth / clientWidth / scrollWidth (및 -Height)와 관련하여 StackOverflow에 대한 몇 가지 질문이 있지만 해당 값이 무엇인지에 대한 포괄적 인 설명은 없습니다.
또한 웹상에서 혼란 스럽거나 잘못된 정보를 제공하는 여러 출처가 있습니다.
시각적 힌트를 포함하여 완전한 설명을 제공 할 수 있습니까? 또한 이러한 값을 사용하여 스크롤 막대 너비를 계산할 수 있습니까?
OffsetWidth / clientWidth / scrollWidth (및 -Height)와 관련하여 StackOverflow에 대한 몇 가지 질문이 있지만 해당 값이 무엇인지에 대한 포괄적 인 설명은 없습니다.
또한 웹상에서 혼란 스럽거나 잘못된 정보를 제공하는 여러 출처가 있습니다.
시각적 힌트를 포함하여 완전한 설명을 제공 할 수 있습니까? 또한 이러한 값을 사용하여 스크롤 막대 너비를 계산할 수 있습니까?
답변:
CSS 상자 모델은 특히 내용 스크롤과 관련하여 다소 복잡합니다. 브라우저는 CSS의 값을 사용하여 상자를 그리지 만 CSS 만 있으면 JS를 사용하여 모든 차원을 결정하는 것이 간단하지 않습니다.
각 요소는 사용자의 편의를 위해 여섯 개 DOM의 속성이 왜 그 : offsetWidth
, offsetHeight
, clientWidth
, clientHeight
, scrollWidth
와 scrollHeight
. 현재 시각적 레이아웃을 나타내는 읽기 전용 특성이며 모두 정수입니다 (따라서 반올림 오류가 발생할 수 있음).
그것들을 자세히 살펴 봅시다 :
offsetWidth
, offsetHeight
: 모든 테두리를 표시하는 시각적 상자의 크기입니다. 요소에 width
/ height
및 패딩 및 테두리 를 추가하여 계산할 수 있습니다.display: block
clientWidth
, clientHeight
: 테두리 나 스크롤 막대를 포함하지 않고 패딩을 포함하는 상자 내용의 시각적 부분. CSS에서 직접 계산할 수 없으며 시스템의 스크롤 막대 크기에 따라 다릅니다.scrollWidth
, scrollHeight
: 현재 스크롤 영역 밖에 숨겨져있는 부분을 포함하여 모든 상자 내용의 크기입니다. CSS에서 직접 계산할 수 없으며 내용에 따라 다릅니다.이후 offsetWidth
고려 스크롤바 폭을 얻어, 우리는 수식 통해 스크롤 바의 폭을 계산하기 위해 사용할 수있다
scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth
이후 불행하게도, 우리는 오류를 반올림 얻을 수 offsetWidth
와 clientWidth
항상 정수의 실제 크기가 1이 아닌 다른 줌 레벨 분수 될 수 있지만,.
이 점에 유의하십시오
scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth
Chrome에서 스크롤바를 이미 빼고 반환하므로 Chrome에서 안정적으로 작동 하지 않습니다width
. 또한 Chrome은 paddingBottom을 스크롤 내용의 맨 아래로 렌더링하지만 다른 브라우저는 그렇지 않습니다.
naturalWidth
및naturalHeight
scrollHeight
포함 padding-bottom
하지만 포함 scrollWidth
하지 않는 이유padding-right
clientWidth
대한이 document.documentElement.clientWidth
가를 포함 보인다 다른 padding
, borders
그리고margin
어떤 사람들은 어떤 이름이 어떤 가치에 해당하는지 기억하는 데 유용 할 수있는 더 포괄적이고 더 깨끗한 버전을 만들었습니다. Chrome Dev Tool의 색상 코드를 사용했으며 라벨을 대칭으로 구성하여 유추를 더 빨리 선택했습니다.
참고 1 : clientLeft
텍스트 방향이 오른쪽에서 왼쪽으로 설정된 경우 세로 스크롤 막대의 너비도 포함합니다 (이 경우 막대가 왼쪽에 표시되므로).
주 2 : 최 외곽 라인에 가장 가까운 대표 위치 부모 (그 요소 position
속성보다는 다른 값으로 설정되어
static
이상 initial
). 따라서 직접 컨테이너가 배치 된
요소가 아닌 경우 선은 계층 구조에서 첫 번째 컨테이너가 아니라 계층 구조에서 더 높은 다른 요소를 나타냅니다. 배치 된 상위를 찾지 못하면
브라우저는 html
또는 body
요소를 참조로 사용합니다.
누군가가 유용하다고 생각하기를 바랍니다. 내 2 센트;)
scrollWidth를 사용하여 "실제" 컨텐츠 너비 / 높이 를 얻으려면 (CSS 정의 너비 / 높이 상자보다 내용이 더 클 수 있으므로) scrollWidth / Height는 일부 브라우저가 패딩 을 "이동"하는 것처럼 매우 신뢰할 수 없습니다 & paddingBOTTOM 내용이 큰 경우. 그런 다음 패딩을 "너무 넓고 / 높은 콘텐츠"의 오른쪽 / 아래에 배치합니다 (아래 그림 참조).
==> 따라서 일부 브라우저에서 실제 콘텐츠 너비를 얻으려면 스크롤 너비에서 두 패딩을 모두 빼야하고 일부 브라우저에서는 왼쪽 패딩 만 빼면됩니다.
나는 이것에 대한 해결책을 찾았고 이것을 주석으로 추가하고 싶었지만 허용되지 않았다. 그래서 나는 "움직이는 패딩"과 "신뢰할 수없는 scrollWidth"와 관련하여 사진을 찍어 조금 더 명확하게 만들었습니다. BLUE AREA에서 "REAL"CONTENT WIDTH를 얻는 방법에 대한 솔루션을 찾으십시오!
이것이 더 명확 해 지길 바랍니다.
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
bcr.height : 330 (chrome53, ff49, safari9, edge13, ie11)
clientWidth : 505 (chrome53, ff49, safari9)
clientHeight : 320 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth : 505 (chrome53, safari9, ff49)
div2
clientHeight : 290 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth : 475 (chrome53, safari9, ff49)
div3
clientHeight : 320 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth : 505 (chrome53, safari9, ff49)
따라서 edge13 및 ie11에서 boundingClientRect의 높이 값 (예상 300 대신 299.9999694824219 대신 300)을 제외하고이 결과의 이론이 작동 함을 확인했습니다.
여기에서 이러한 개념에 대한 나의 정의는 다음과 같습니다.
참고 : 기본 세로 스크롤 막대의 너비는 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 에서 내 테스트 페이지를 볼 수 있습니다 .
element.getBoundingClientRect()
( developer.mozilla.org/en-US/docs/Web/API/Element.clientWidth 참고 )