• [JS] 요소의 요모조모 (1) - 문서 내 요소의 크기와 위치

    2019. 12. 3.

    by. 나나 (nykim)

    요소의 크기

    1. 요소의 크기 알아내기

     

    여기, 이렇게 생긴 요소가 하나 있습니다.

    이 아이가 가진 CSS 속성은 아래와 같습니다.

     

    .box {
      width: 100px;
      height: 100px;
      padding: 50px;
      border: 50px solid #F16B6F;
      margin: 50px;
    }

     

    만약 이런 CSS 속성을 모르거나, 속성이 유동적으로 바뀌는 상황에서 요소의 크기를 알아내고 싶다면 어떻게 해야할까요?

    네, 그냥 콘솔에 찍으면 됩니다.

     

    var box = document.querySelector(".box");
    console.dir(box.getBoundingClientRect());

     

    이럴 때 쓰라고 있는 게 getBoundingClientRect() 입니다. [MDN 링크]

    이름이 어려운데 에라 모르겠다 일단 콘솔을 봅시다.

     

     

    오?! 뭔가 숫자를 던져주네요.

    width, height가 300으로 표시되는 걸 알 수 있습니다. 200에 패딩값(50)과 보더값(50)이 합쳐져서 300이겠네요.

    (box-sizing: content-box일 때, border는 기본적으로 width / height 값에 포함됩니다.)

    left나 right에 대한 건 조금 있다 다루기로 하고 넘어가죠.

     

     

     

     

    음... 근데 이보다 더 쉽게 width를 알아낼 순 없을까요?

    더 쉬운 말이 있으니 바로 offsetWidth 입니다.

     

     

    box.offsetWidth === box.getBoundingClientRect().width; //TRUE

     

    이 둘이 뭔가 미묘하게 다른 거 같다면, 그건 스펠링...이 아니라 Transform을 했을 때 그 결과를 반영하는지가 다릅니다.

    box에다 통크게 transform: scale(2); 를 해주고 둘의 값을 비교해봅시다!

     

    console.dir(box.offsetWidth); //300
    console.dir(box.getBoundingClientRect().width); //600

     

    넵. offsetWidth는 여전히 본래의 크기를 나타내지만, getBoundingClientRect().width 헉헉 길다 는 두 배 커진 크기를 나타냅니다.

    따라서 Transform 같은 인터렉션이 있는 상태에서 정확한 수치 계산이 필요하다면 겟바운딩어쩌구를 써줘야겠죠?

     

     

     

     

    2. 보더 값을 제외한 크기 알아내기

     

    난 보더 싫어!! 보더값 빼고 크기 알아낼 거야!!!! 싶을 때가 있죠? (있겠죠 언젠가...)

    그럴 때 SSG 꺼내쓰는 게 clientWidth / clientHeight입니다.

    이 값은 보더나 스크롤바 크기를 무시하고, 패딩만을 포함한 요소의 크기를 리턴합니다.

     

     

    따라서 100(너비)+50(왼쪽 패딩값)+50(오른쪽 패딩값) = 200이 나오게 됩니다.

     

     

     

     

    3. 보이지 않는 부분도 포함하는 크기 알아내기

     

    CSS를 다루다보면 overflow를 자주 쓰게 되는데, 이렇게 가려지는 부분까지 포함해 크기를 알아내는 방법도 있습니다.

    바로 scrollWidth / scrollHeight 입니다.

     

    .parent 아래에 .child라는 자식 요소를 넣어봤습니다.

     

    <div class="parent">
      <div class="child">
        Nanalike
      </div>
    </div>
    .parent {
      position: relative;
      margin: 50px;
      height: 500px;
      border: 10px solid #3C3530;
      overflow: auto;
    }
    
    .child {
      padding: 50px;
      width: 800px;
      height: 1000px;
    }

     

    그리고 parent의 scrollWidth / scrollHeight를 확인하면...

     

    console.dir(parent.scrollWidth); //900
    console.dir(parent.scrollHeight); //1100

     

    800(너비) + 50(왼쪽 패딩값) + 50(오른쪽 패딩값) = 900인 걸 볼 수 있습니다.

     

     

    이렇게 튀어나온 부분까지 알고 싶다면 scrollWidth / scrollHeight 를 적극 사용합시다.

     

     

     

     

     


     

     

    요소의 위치

    1. 요소의 위치 알아내기

    이번에는 요소가 어디에 위치해 있는지 알아봅시다.

    아까 썼던 clientgetBoundingClientRect()를 다시 확인해보면...

     

     

    top, left, right, bottom 이라는 프로퍼티를 볼 수 있습니다.

     

    top과 left는 문서로부터 얼마나 떨어져 있는지를 보여줍니다.

    마진값이 50이었죠? 따라서 위로부터 50, 왼쪽으로부터 50 떨어져있으니 top:50, left:50이 됩니다.

     

     

    bottom이랑 right은 top과 left로부터 요소의 끝과 오른쪽이 어디있는지를 나타냅니다.

    그러므로 값은 50(왼쪽 마진값) + 50(왼쪽 패딩값) + 200(너비) + 50(오른쪽 패딩값) = 350이 되죠.

     

     

     

    한편, 이 요소가 부모 아래에 있으면 어떻게 계산될까요?

     

    .parent {
      padding: 50px;
      margin: 50px;
      border: 10px solid #3C3530;
    }

     

    콘솔에 찍어본 결과는...?!

     

     

    우선 left값을 봅시다. 본래는 50(왼쪽 마진값)이었죠.

    그런데 부모의 50(왼쪽 마진값)+50(왼쪽 패딩값)+10(보더값)=110이 합쳐지면서 160이 되었습니다.

    bottom도 기존 350에 부모의 110이 더해진 460이 나온 걸 볼 수가 있고요.

     

    결국 getBoundingClientRect().top은 부모가 아닌, 문서(정확히는 뷰포트)를 기준으로 하고 있음을 알 수 있습니다.

    그걸 어떻게 알 수 있냐면, offsetParent 프로퍼티를 콘솔에 찍어보면 됩니다. 이 프로퍼티는 가장 가까운 부모 객체에 대한 참조를 리턴합니다.

     

    console.dir(box.offsetParent);

     

     

    그럼 body가 콘솔에 찍히는 걸 볼 수 있습니다. 엌 .parent가 부모가 아니였단 말야?!! (출생의 비밀)

    왜냐면 우린 position: relative; 를 넣어주지 않았으니까요.

    이렇게 지정된 부모가 없다면 offsetParent는 가장 가까운 td, th, table 또는 body를 리턴합니다.

     

     

     

    2. 부모를 기준으로 하는 상대적 위치 알아내기

    그렇다면 부모를 기준으로 한 값을 알고 싶을 땐 뭘 써야 할까요?

    offsetTop / offsetLeft 프로퍼티를 써주면 됩니다.

     

    부모를 .parent로 지정해준 다음 box를 콘솔에 찍어봅니다.

     

     

    계산해보면 부모의 패딩(50) + 자신의 패딩(50) = 100만큼 떨어져 있음을 알 수 있습니다.

     

    이 상태에서 box.getgetBoundingClientRect().left를 해보면 어떻게 될까요?

    부모의 마진(50) + 부모의 보더(10) = 60에다 100을 더한 160이 출력됩니다.

     

     


     

     

    마지막으로 정리하고 넘어갑니다 👏

     

    요소의 크기 알아내기

    - 보더패딩 다~ 포함한 전체 크기 알려줘! : offsetWidth

    - Transform 렌더링도 포함한 크기 알려줘! : getBoundingClientRect().width

    - 보더값 제외한 크기 알려줘! : clientWidth

    - 스크롤 할 수 있는 전체 크기 알려줘! : scrollWidth

     

    요소의 위치 알아내기

    - 문서(뷰포트)로부터 위치 알려줘! : getgetBoundingClientRect().top

    - 부모로부터 위치 알려줘! : offsetTop

     

     

    출처: https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively

     

     

     

    참고 자료

    https://www.opentutorials.org/module/904/7112

     

     

     

     

    'Study > JavaScript' 카테고리의 다른 글

    [Node.js] 유튜브 클론 01  (0) 2020.02.24
    [JS] 스크롤 페이드인 효과  (2) 2019.12.05
    [JS] 요소의 요모조모 (1) - 문서 내 요소의 크기와 위치  (0) 2019.12.03
    [JS] Text RPG 만들기  (0) 2019.11.12
    [JS] 객체의 상속  (0) 2019.11.05
    [JS] 브라우저의 객체  (0) 2019.11.04

    댓글 0