요소의 컨테이닝 블록을 식별하는 방법

이나리·2022년 8월 22일
0

컨테이닝 블록이라는 용어를 처음 들었을 때, 용어의 글자를 보아 단순히 부모 영역을 가리킨다고 생각했습니다.

물론, 이것이 틀린 답은 아니었지만 그렇다고 항상 부모 영역을 가리키는 것도 아니었는데요.

이번에는 이 컨테이닝 블록이란 것이 무엇이고, 이 컨테이닝 블록을 결정하는 것들에는 어떤 것들이 있는지 알아보고자 합니다.

Box Model

브라우저가 웹페이지에 요소를 배치할 때, 각 요소마다 다음과 같은 박스 모델이 생성됩니다.

  1. Content 영역
    요소의 컨텐츠를 표시하는 영역입니다. 주로 width, height 프로퍼티를 사용하여 요소의 컨텐츠 크기를 결정합니다.
  2. Padding 영역
    요소의 컨텐츠와 테두리 사이의 영역입니다.
  3. Border 영역
    요소의 테두리를 나타내는 영역으로, 요소의 컨텐츠와 패딩을 감쌉니다.
  4. Margin 영역
    요소와 그 요소에 인접하는 요소 사이의 간격을 나타내는 영역입니다.

컨테이닝 블록이란?

컨테이닝 블록은 위와 같은 박스의 크기와 위치를 결정하는데 영향을 미치는 또 다른 박스 영역이라고 할 수 있습니다.

컨테이닝 블록을 식별하는 방법

보통 html 문서에 요소가 배치될 때, 부모 요소가 자식 요소를 감싸고 그 안에 또 다른 자식 요소가 있을 수 있습니다.

문서의 루트 요소인 html 요소는 초기 컨테이닝 블록으로 지정되어 있어, 모든 요소에는 항상 컨테이닝 블록이 존재한다는 사실도 짐작해볼 수 있습니다.

그렇다면 각 요소의 컨테이닝 블록은 어떻게 식별할 수 있을까요?

각 요소의 컨테이닝 블록은 해당 요소의 position 속성값이 무엇이냐에 따라 결정됩니다.

1. position: static / relative / sticky

요소의 position 속성이 static, relative, sticky 중 하나라면, 블록 요소이거나 bfc를 형성하는 가장 가까운 조상 요소의 content 영역이 컨테이닝 블록이 됩니다.

이 케이스에 해당하게 되면, 해당 요소를 감싸고 있는 부모 요소가 컨테이닝 블록이 될 수도 있지만, 꼭 그렇지만은 않다는 사실을 알 수 있습니다.

아래 예제를 한번 살펴볼까요?

위의 코드에서 나타난 요소들의 컨테이닝 블록은 다음과 같습니다.

  1. first, second 클래스 요소의 컨테이닝 블록: body 요소
  2. span 요소의 컨테이닝 블록: second 클래스 요소
  3. strong 요소의 컨테이닝 블록: body 요소

그 이유를 한번 분석해보겠습니다.

first 클래스 요소에는 어떤 position 속성도 전달되지 않았으므로, 기본값인 static이 적용됩니다. 따라서 가장 가까운 블록 요소인 body 요소가 컨테이닝 블록이 됩니다.

second 클래스 요소의 position 속성값은 relative이므로, first 클래스 요소와 마찬가지로 가장 가까운 블록 요소인 body 요소가 컨테이닝 블록이 됩니다.

span 요소도 마찬가지로 position: static 이므로 가장 가까운 조상 요소 중에서 블록 요소이거나, bfc를 형성하는 요소가 컨테이닝 블록이 됩니다. 이번에는 second 클래스 요소가 여기에 해당합니다.

그런데 왜 strong 요소의 컨테이닝 블록은 body 요소가 되었을까요?

strong 요소의 가장 가까운 조상 요소는 third 클래스 요소이지만, 이 요소는 인라인 요소이기 때문에 컨테이닝 블록이 될 수 없습니다. 따라서 third 클래스 요소의 부모 요소인 body 요소가 컨테이닝 블록이 되는 것입니다.

또한, relative가 적용된 요소는 일반적인 문서의 배치 흐름은 그대로 유지하면서, 자신의 배치된 원래 위치를 기준으로 움직입니다.

2. position: absolute

요소의 position 속성이 absolute라면, position 속성이 static이 아닌 가장 가까운 조상 요소의 padding 영역이 컨테이닝 블록이 됩니다.

이번에는 앞선 예제에서, span 요소에 position: absolute 속성을 추가했습니다.
이때 span 요소의 컨테이닝 블록은 가장 가까운 조상 요소인 second 클래스 요소에 position 속성이 relative이 적용되어 있으므로, second 클래스 요소가 됩니다.

또한, position 속성값이 static에서 absolute로 변경되면서, 일반적인 문서의 배치 흐름에서 벗어나 자신의 컨테이닝 블록을 상대적 기준점으로 잡고 요소가 움직이는 것도 확인할 수 있습니다.

3. position: fixed

요소의 position 속성이 fixed라면, 컨테이닝 블록은 보통 viewport 영역이 됩니다.
이 경우, 컨테이닝 블록은 루트 요소인 html 이 됩니다.

이번에는 span 요소 position 속성을 fixed로 변경했습니다.
이때 span 요소의 컨테이닝 블록은 초기 컨테이닝 블록인 html이 되기 때문에, span 요소의 위치가 html 요소를 기준으로 움직입니다.

absolute와 동일하게 일반적인 문서의 배치 흐름에서 벗어나, 자신의 컨테이닝 블록을 기준으로 움직이지만, 스크롤이 생겨도 화면에서 사라지지 않습니다.

4. position: absolute / fixed

요소의 position 속성이 absolute or fixed라면, 아래 중 하나라도 해당되는 가장 가까운 조상 요소의 padding 영역이 컨테이닝 블록이 됩니다.

  1. transform, perspective 속성값이 none 이 아닌 경우
  2. will-change 속성값이 transform or perspective 인 경우
  3. filter 속성값이 none인 경우 or will-change 속성값이 filter인 경우 (파이어폭스에서만 동작함)
  4. contain 속성값이 paint 인 경우
  5. backdrop-filter 속성값이 none이 아닌 경우

위의 예제를 보시면, span 요소가 position: absolute 속성을 가졌지만, 가장 가까운 조상 요소가 transform 속성이 none인지 아닌지에 따라, 다른 컨테이닝 블록을 가지는 것을 확인할 수 있습니다.

(위의 5가지 경우에서 transform 속성 외에는 실제로 사용해 본 적이 없어서, 예시가 많이 부족한 점 양해 부탁드립니다.)

초기 컨테이닝 블록

css를 한번이라도 사용해봤다면, 컨테이닝 블록이라는 개념에 대해서 처음 들어볼 순 있어도, 그 개념을 사용한 코드에 대해서는 익숙할 수 있습니다.

보통 특정 요소를 문서에 띄우기 위해, 요소에 position: absolute 속성값을 많이 전달하죠. 바로 이 단순한 코드에 컨테이닝 블록의 개념이 포함되어 있습니다.

이 코드를 조금 구체화하여 다음과 같은 코드를 작성해봤습니다. 이때 div 요소의 컨테이닝 블록은 누구일까요?

<body>
  <div>안녕하세요 나의 컨테이닝 블록은 누구입니까?</div>
</body>
div {
  position: absolute;
  top: 50px;
  left: 50px;
  width: 50px;
  height: 50px;
  border: 1px solid black;
}

정답은 루트 요소인 html입니다. position: absolute 속성값이 적용된 요소의 컨테이닝 블록은 position 속성이 static이 아닌 가장 가까운 조상 요소여야 합니다.

그런데, div 요소에서 가장 가까운 조상 요소인 body는 적용된 position 속성값이 없으므로 기본값인 static이 적용된 상태입니다. 따라서 body는 div 요소의 컨테이닝 블록이 될 수 없습니다.

그 다음 가장 가까운 조상 요소인 html은 초기 컨테이닝 블록으로서, 모든 요소의 컨테이닝 블록이 될 수 있으므로 div 요소의 컨테이닝 블록이 html 요소가 되는 것입니다.

기준이 되는 요소에 position 속성을 전달하지 않았는데도 요소가 문서 위로 띄워질 수 있었던 이유가 바로 이 초기 컨테이닝 블록이 존재하기 때문입니다.

이 컨테이닝 블록은 초기 컨테이닝 블록으로서, 모든 요소의 크기와 위치를 지정하는데 가장 기본이 됩니다.

컨테이닝 블록이 필요한 이유

보통 요소의 크기와 위치를 지정할 때, px 과 같은 절대적 단위도 사용하지만 % 라는 상대적 단위도 사용합니다. 하지만 이런 상대적 단위는 기준점이 필요합니다.
요소의 크기를 1% 라고 했을 때, 우리는 이것이 얼만큼인지 정확하게 판단할 수 없습니다. 그에 대한 기준점이 주어져야만 이를 가늠할 수 있죠.

위에 작성한 예제 코드도 잘 보시면, 제가 일부러 요소의 width 값을 50%로 표시했습니다.
컨테이닝 블록은 요소의 크기와 위치에 영향을 미치기 때문에, 그게 누구인지에 따라 요소의 크기가 달라지는 것을 확인하실 수 있으셨을 겁니다.

이를 조금 더 구체적으로 정리해보면,

요소의 크기를 결정하는 속성에는 width, height, padding, margin 이 있고,
요소의 위치를 결정하는 속성에는 top, bottom, left, right 가 있습니다.

  1. width, padding, margin, left, right 는 컨테이닝 블록의 width 값으로부터 계산됩니다.

  2. height, top, bottom 은 컨테이닝 블록의 height 값으로부터 계산됩니다.

이와 관련하여 요소의 크기를 계산하는 예제를 보고 싶으시다면, MDN 예제를 참고하시면 좋을 것 같습니다.

0개의 댓글