DOM의 사이즈에 대해서

in #kr4 years ago

DOM의 사이즈를 구하는 방법에는 여러가지가 있습니다.
하지만 사이즈를 구하면서도 발생할 수 있는 여러가지 경우의 수가 있어서 사이즈를 구할때
내가 어떤 사이즈를 구하려고 하는지 신중하게 잘 판단하셔서 코드를 사용하셔야 합니다.

자바스크립트로 사이즈를 구하는 방법

자바스크립트에는 사이즈를 구할 수 있도록 도와주는 메소드와 프로퍼티들이 존재합니다. 그리고 자바스크립트 DOM은 style이라는 속성이 있는데 style에 들어가 있는 사이즈를 바로 가지고 올 수 도 있습니다.

순수 자바스크립트로만 사이즈를 가지고 올 수 있는 방법은 다음과 같은 여러가지 방법이 존재합니다.

<div id="pan" style="width: 500px;">
    hello
</div>
 <script>
    console.log(parseInt(document.getElementById("pan").style.width));
    console.log(document.getElementById("pan").scrollWidth);
    console.log(document.getElementById("pan").clientWidth);
    console.log(document.getElementById("pan").offsetWidth);
    console.log(document.getElementById("pan").getClientRects()[0].width);
    console.log(document.getElementById("pan").getBoundingClientRect().width);
</script>

실행해보면 모두 동일한 결과물을 내고 있는거 처럼 보이는데,
과연 특정한 조건에서도 동일한 결과값을 뱉어내는지 확인을 해봐야합니다.

DOM 이 보이지 않을 때

DOM에 스타일로 display: none;이 같이 들어가게 되면 결과값을 서로 달라지기 시작합니다.
우선 1번째 document.getElementById("pan").style.width의 경우 style에 넣은 값은 스트링 값이고 가장 우선순위가 높기 때문에 width를 가지고 와서 parseInt로 변환을 해주면 이전과 동일한 500이라는 결과값을 가지고 올 수 있습니다.

하지만, 여기에서 가장 주의해야할 것이 하나 있는데 바로 document.getElementById("pan").getClientRects()[0].width 입니다. getClientRects()는 값이 없을때 빈객체에 length가 0인 ArrayLike 오브젝트를 리턴해주게 됩니다.

그렇기 때문에 0이라는 프로퍼티에 접근을 하면 undefined가 나오는데 width를 접근하게 되면 Cannot read property 'width' of undefined 라는 에러메시지를 접할 수 있습니다.

그렇기 때문에 만약에 사이즈를 구할일이 있다면, getClientRects()가 아닌 getBoundingClientRect를 사용하시길 권장드립니다.

DOM이 안보일때는 reflow가 일어나지 않습니다. 그렇기 때문에 DOM트리를 구성하는 속도는 빨라지지만 실제로 DOM의 사이즈를 구할 수 없습니다.
만약에 DOM에 실제 크기를 구하고자 한다면, DOM의 스타일중에 visibility라는 스타일 속성이 존재하는데 해당 스타일을 hidden을 주고, display를 block으로 변경한 다음 사이즈를 구하고 다시 display: none으로 변경하고 visibility를 제거하거나 visible로 주시게 되면 됩니다.
이런 문제는 JQuery를 사용하는 개발자라면 간단하게 width()함수를 이용하면 해결할 수 있지만, 내가 가지고 오려고 하는 DOM의 부모DOM이 display속성이 none이 들어가 있다면, width()를 호출해도 원하는 값을 가지고 올 수는 없으니 참고 하시면 좋을것 같습니다.

하위 DOM이 존재하는 경우

대부분의 DOM들은 하위 DOM을 가지고 있습니다.
때로는 하위 DOM이 부모 DOM보다 더 큰 사이즈를 가지고 있는데 이 때도 사이즈를 가지고 올때 확인해야 되는 부분이 있습니다.

아마 대부분 분들이 눈치를 채셨겠지만, 이때는 document.getElementById("pan").scrollWidth의 크기만 달라지게 됩니다. scrollWidth는 스크롤의 값만큼 현재 크기에 더해줍니다. (그냥 스크롤 전체 사이즈라고 생각하시는게 좋습니다.)

그렇기 때문에 하위 DOM의 크기를 고려해야 되는 상황에서 사용하시면 되고 이거는 사용하지 않아야 된다가 아니라 특정한 상황을 고려해서 잘 사용해야 된다 입니다.

하지만, 현재 DOM 보다 상위 DOM이 더 작다고해서 현재 DOM에 사이즈를 가지고 올때 영향을 미치지는 않으니 그런 점은 고려하지 않으셔도 괜찮을 것 같습니다.

scrollWidth는 언제 주로 사용하냐면 현재 DOM에 스크롤이 존재하는지 확인할때 사용할 수 있습니다.
scrollWidth가 clientWidth보다 크다면 스크롤이 있는 DOM이라고 판단할 수 있습니다.
그래서 잘만 활용하신다면 불필요한 scroll이벤트를 주지 않고 개발을 할 수 있습니다.

border가 존재하는 경우

border가 존재하는 경우에도 역시 값을 달라집니다.
이번에는 clientWidth와 offsetWidth입니다. border는 실제로 컨텐츠 영역은 아니지만 확실히 width를 가지고 있는 스타일 속성중에 하나입니다.

border가 적용된 상태에서 또 다시 사이즈를 확인해보면 clientWidth혼자 다른 값을 취하고 있는 것을 확인할 수 있습니다. clientWidth같은 경우에는 눈에 보이는 실제 컨텐츠들이 들어가는 영역의 width를 가지고 나머지는 해당 돔이 가지고 있는 전체 사이즈를 의미하게 됩니다.

그렇기 때문에 실제 화면에 보이는 영역의 사이즈를 구하고 싶다면 clientWidth를 가지고 작업을 하시면 됩니다.

transform 효과를 사용할 때

사실 transform를 사용할 때 역시 주의해야할 것이 있습니다.
getBoundingClientRect는 DOM의 width값이 아닌 가장왼쪽부터 가장 오른쪽 까지의 길이를 리턴합니다. 그렇기 때문에 실제 100px짜리의 dom이 회전을 하게 된다면, 넓이가 더 줄어들거나 약간 더 늘어날 수 도있습니다.

Sort:  

Congratulations @noreco! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 1 year!

Click here to view your Board

Support SteemitBoard's project! Vote for its witness and get one more award!

Congratulations @noreco! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Coin Marketplace

STEEM 0.28
TRX 0.07
JST 0.042
BTC 30364.90
ETH 2080.58
USDT 1.00
SBD 2.61