HyunJun 기술 블로그

offset, getBoundingClientRect(), scroll 본문

JavaScript

offset, getBoundingClientRect(), scroll

공부 좋아 2023. 7. 18. 10:49
728x90
반응형

1. offset

1) offsetHeight, offsetWidth

  • offsetHeight는 현재 엘리먼트의 높이를 의미하고, offsetWidth는 현재 엘리먼트의 넓이를 의미한다.

2) offsetTop, offsetLeft

  • offsetTop은 부모 요소 중 relative, absolute, fixed 등의 포지션을 가진 첫 부모 요소의 위치를 기준으로 해당 위치부터 타겟 엘리먼트의 Top까지 몇 픽셀 떨어져 있는지를 나타낸다.
  • offsetLeft는 Top과 동일하지만 부모 요소로부터 타겟 엘리먼트의 Left까지 몇 픽셀 떨어져 있는지 거리를 나타낸다 부모 요소를 찾지 못할 경우 body 엘리먼트를 기준으로 잡게 된다.

3) offsetParent

  • 마찬가지로 부모 요소 중 relative, absolute, fixed의 요소의 엘리먼트를 리턴한다. 적당한 부모 요소를 찾지 못할 경우 body 엘리먼트를 리턴한다.

예제 코드

  <body>
    <div class="div-box">1</div>
    <div class="div-box">2</div>
    <div style="position: relative">
      <div class="div-box">3</div>
    </div>

    <script>
      let elements = [...document.getElementsByClassName("div-box")];

      elements.forEach((element, index) => {
        element.style.width = "50px";
        element.style.height = "50px";
        element.style.border = "1px solid black";

        console.log(`${index + 1} 엘리먼트의 높이: ${element.offsetHeight}`);
        console.log(`${index + 1} 엘리먼트의 넓이: ${element.offsetWidth}`);

        console.log(`${index + 1} 엘리먼트 Top까지의 거리: ${element.offsetTop}`);
        console.log(`${index + 1} 엘리먼트 Left까지의 거리: ${element.offsetLeft}`);

        console.log(`${index + 1} 부모 요소 찾기: `, element.offsetParent);
      });
    </script>
  </body>

 

2. getBoundingClientRect()

offset과 다르게, 해당 DOM 요소에 대해서, 현재 위치한 윈도우 화면(창) 기준 어디에 위치해있는지 정확한 좌표를 가지고 올 수 있다. 이때 부모 요소와 상관없이 절대적인 위치를 가지고 온다. 이 말인즉슨, 화면의 이동에 따라 top, bottom 등의 값이 바뀌게 된다.

1) width, height

해당 DOM 엘리먼트의 width, height를 가지고 온다.

 

2) top, left

  • top: 브라우저 윈도우 창의 상단 경계선(주소창 아래쪽)을 기준으로 해당 엘리먼트의 top까지 몇 픽셀 떨어져 있는지 계산해 준다. 이 말인즉슨 화면 스크롤이 되어 엘리먼트가 안 보이게 위로 올라갔다면 음수 값이 리턴된다.
  • left: 브라우저 윈도우 창의 왼쪽 경계선을 기준으로 해당 엘리먼트의 left가 몇 픽셀 떨어져 있는지 계산해 준다.

3) bottom, right 

  • bottom: 브라우저 윈도우 창의 상단 경계선을 기준으로 해당 엘리먼트의 bottom까지 몇 픽셀 떨어져 있는지 계산해 준다.
  • right: 브라우저 윈도우 창의 왼쪽 경계선을 기준으로 해당 엘리먼트의 right까지 몇 픽셀 떨어져 있는지 계산해 준다.

3) x, y

x: left, y: top과 같다.

 

예제 코드

  <style>
    body {
      margin: 0;
    }
    #div-box {
      background-color: beige;

      position: relative;
      width: 50px;
      height: 50px;
      left: 60px;
      top: 40px;
    }
  </style>
  <body>
    <div id="div-box">div</div>

    <script>
      let element = document.getElementById("div-box");

      elementRect = element.getBoundingClientRect();

      console.log(`엘리먼트의 높이: ${elementRect.height}`);
      console.log(`엘리먼트의 넓이: ${elementRect.width}`);

      console.log(`엘리먼트 Top까지의 거리: ${elementRect.top}`);
      console.log(`엘리먼트 Left까지의 거리: ${elementRect.left}`);

      console.log(`엘리먼트 Bottom까지의 거리: ${elementRect.bottom}`);
      console.log(`엘리먼트 Right까지의 거리: ${elementRect.right}`);

      console.log(`x 좌표: ${elementRect.x}`);
      console.log(`y 좌표: ${elementRect.y}`);

      document.addEventListener("scroll", (e) => {
        // console.log(document.getElementsByClassName("div-box")[0].offsetTop);
        // console.log(document.getElementsByClassName("div-box")[0].getBoundingClientRect().top);
      });
    </script>
  </body>

 

body의 height를 길게 주고 아래처럼 리스너를 등록해 보았다.

      document.addEventListener("scroll", (e) => {
        let element = document.getElementById("div-box");
        rect = element.getBoundingClientRect();

        console.log(element.offsetTop);

        console.log("top: ", rect.top);
        console.log("left: ", rect.left);
        console.log("bottom: ", rect.bottom);
        console.log("right: ", rect.right);

        console.log("x: ", rect.x);
        console.log("y: ", rect.y);

        console.log("width: ", rect.width);
        console.log("height: ", rect.height);
      });

offset과는 다르게 화면이 이동함에 따라 값들이 변경된다. (가로 스크롤 변경 시도 동일하게 left, right가 변하게 된다.)

 

단순하게 생각했을 때는 무조건 getBoundingClientRect() 방식이 좋아 보일 수 있다. 하지만 사실 좋고 나쁘고 차이가 아니라,

  • 스크롤이라던지 화면의 이동에 따라 좌표를 찾으려면 무조건 getBoundingClientRect() 방식을 써야 하고
  • 부모 요소를 기준으로 정적인 위치를 잡으려면 무조건 offset 방식을 사용해야 한다.
728x90
반응형
Comments