BFC는 언제 사용해야 하는가?

15349 단어 CSSCSS

블록 서식 맥락(block format context)은 웹 페이지를 렌더링하는 시각적 CSS의 일부로서, 블록 박스의 레이아웃이 발생하는 지점과 플로팅 요소의 상호작용 범위를 결정하는 범위입니다.

위는 MDN에 나와있는 정의인데 이것만 보고 정확하게 BFC가 무엇인지는 감이 오지 않아서 BFC의 정의보다는 언제 사용해야 되는 개념인지에 초점을 맞추었다. 일단 내가 대략적으로 이해한 것은 BFC는 미니 레이아웃이라는 것이다. 어떤 요소에 새로운 BFC를 적용하면 하위 요소를 대상으로 한 독립적인 레이아웃이 생성되며 다른 요소들과도 레이아웃 관계를 형성할 수 있다. 이 말도 이해하기 힘들다면 그냥 의도한 것과 다르게 배치되는 레이아웃을 올바르게 잡는 방법으로 BFC를 적용한다고 생각하면 된다.

BFC는 다음과 같은 상황에서 생성된다.

  • 문서의 루트 요소
  • 플로팅 요소(float이 none이 아님).
  • 절대 위치를 지정한 요소(position이 absolute 또는 fixed).
  • 인라인 블록(display가 inline-block).
  • 표 칸(display가 table-cell, HTML 표 칸의 기본값).
  • 표 주석(display가 table-caption, HTML 표 주석의 기본값).
  • display가 tabletable-rowtable-row-grouptable-header-grouptable-footer-group (HTML 표에서, 각각 표 전체, 행, 본문, 헤더, 푸터의 기본값) 또는 inline-table인 요소가 암시적으로 생성한 무명 칸.
  • overflow가 visible이 아닌 블록 요소.
  • display가 flow-root.
  • contain이 layoutcontentpaint.
  • 스스로 플렉스, 그리드, 테이블 컨테이너가 아닌 경우의 플렉스 항목(display가 flex 또는 inline-flex인 요소의 바로 아래 자식)
  • 스스로 플렉스, 그리드, 테이블 컨테이너가 아닌 경우의 그리드 항목(display가 grid 또는 inline-grid인 요소의 바로 아래 자식)
  • 다열 컨테이너(column-count 또는 column-width 가 auto가 아닌 경우. column-count: 1 포함).
  • column-span 이 all인 경우. 해당하는 요소가 다열 컨테이너 안에 위치하지 않아도 항상 새로운 블록 서식 맥락을 생성해야 합니다.

일반적인 맥락에서는 다음과 같은 상황들이 발생할 수 있다.

  • float된 요소를 부모 요소가 포함하지 못하는 현상
  • float된 요소를 글자들이 감싸는 현상
  • 마진 겹침 현상

BFC는 주로 위치 설정과 float 해제를 위해 사용되는 것이다.
그럼 지금부터 각 상황마다 BFC가 문제를 어떻게 해결하는 지 알아보자.


🚩 float된 요소 포함하기

사실 float된 요소를 포함하지 못하는 상황은 clearfix로 해결하는 것이 가장 좋다. clearfix는 CSS에 :after라는 가상요소를 사용해서 HTML문서에 존재하지 않는 새로운 요소를 생성한 후 clear:both속성을 주어 해결하는 방법이다. clearfix 외에도 float된 요소를 부모가 포함하는 방법은 많았지만 단점이 있기 때문에 좋은 방법은 아니었다. clearfix를 제외한 거의 모든 방법들이 새 BFC를 생성함으로 문제를 해결하는 것이라고 볼 수 있다.

부모 요소에게도 float를 주는 방법, 부모의 displayinline-block으로 설정하는 방법, 부모의 overflowautohidden으로 설정하는 방법, 빈 블록을 생성하는 방법 모두 사실은 BFC를 생성한다. 즉 BFC를 새롭게 만들어 clearing 한 것이다.

이렇게 부모 container가 float된 이미지를 담지 못할 때 부모에게 overflow:hidden을 주면 자식 요소를 포함할 수 있게 된다. container에 새 BFC를 준 것이다.

.container {
  background: #f6e58d;
  overflow: hidden; /*new BFC*/
}
img {
  float: left;
}

🚩 float된 요소를 글자들이 감싸는 현상 방지

위의 예에서 만약 텍스트의 길이가 더 늘어나면 다음과 같이 글자가 float된 이미지를 감싸게 된다. 그렇다면 이런 현상이 왜 발생하는 것일까?


p태그는 검은색 영역인데 float된 요소 아래에서도 크기를 차지하고 있는 것을 확인할 수 있다. p태그의 전체 크기는 줄어들지 않고, 텍스트를 포함하는 부분만 float된 요소를 피해서 흐르는 것이 특징이다. 텍스트가 더 증가한다면 텍스트를 포함한 부분의 넓이가 줄어들지 않아도 되기 때문에 p태그의 왼쪽부터 다시 흐르기 시작한다. 그래서 글자가 float된 요소를 감싸는 현상이 발생하는 것이다.

p태그에 새로운 BFC를 적용한다면 더이상 container의 왼쪽 끝까지 위치를 가지지 않을 것이기 때문에 p태그에 overflow:hidden을 사용하고, background를 주어 크기를 확인했다.

🚩 마진 겹침 현상 제거

마진 겹침 현상(Margin Collapsing)은 block 모델에서 margin이 겹치는 현상을 말한다. 두 개 이상의 블록이 위 아래로 위치할 때 블록의 각 margin이 더해지는 것이 아니라 더 큰 margin으로 설정되는 현상이다.

마진 겹침 현상은 다음과 같은 상황에서 발생할 수 있다.

  1. 인접 형제 박스 간 상하 마진이 겹칠 때
  2. 빈 요소의 상하 마진이 겹칠 때
  3. 부모 박스와 첫 번째(마지막) 자식 박스의 상단(하단) 마진이 겹칠 때
<div class="container">
        <p>I am paragraph one and I have a margin top and bottom of 20px;</p>
        <p>I am paragraph two and I have a margin top and bottom of 20px;</p>
</div>
.container {
  width: 200px;
  background: #f7ce00;
  margin: 40px 0 40px 0;
}
p {
  padding: 0;
  width: 200px;
  margin: 20px 0 20px 0;
  background-color: #0058b5;
  color: #fff;
}

이와 같은 코드에서 container의 marginp태그의 margin이 합쳐져 60px이 전체 margin이 되어야 한다고 생각할 수 있지만 부모 박스와 첫번째 박스의 마진이 겹치기 때문에 마진 겹침 현상이 발생한다. 이때 부모의 margin40px이고, 자식의 margin20px이기 때문에 전체 margin40px로 설정된다.

p태그의 margin이 적용된다면 전체 container의 위 아래에도 노란색이 있어야 한다. 그러나 얻은 결과는 그렇지 않다. 만약 container의 margin을 p태그의 margin보다 작게 한다면 container의 위 아래에서 노란색을 볼 수 있을까? 그렇지 않다. 자식 요소의 margin이 부모 요소의 margin보다 더 크든 작든 상관없이 상쇄된 마진은 부모 박스의 바깥으로만 렌더링 되기 때문이다.

이를 해결하기 위해 css를 다음과 같이 수정하여 새로운 BFC를 준다면 해결할 수 있을 것이다.

.container {
  width: 200px;
  background: #f7ce00;
  margin: 40px 0 40px 0;
  overflow: hidden; /* New BFC */
}
p {
  padding: 0;
  width: 200px;
  margin: 20px 0 20px 0;
  background-color: #0058b5;
  color: #fff;
}

그러나 아직 해결되지 않은 문제가 있다 형제 box간의 마진 겹침 현상이 남아있다. 위쪽 파랑색 박스의 margin20px이고 아래쪽 파랑색 박스의 margin20px이기 때문에 위 아래의 margin이 더해져 40px이 되게 하고픈 상황이 있을 수 있다. 이럴 때도 새로운 BFC를 생성하면 된다.

<div class="container">
        <p>I am paragraph one and I have a margin top and bottom of 20px;</p>
        <div class="newBFC">
            <p>I am paragraph two and I have a margin top and bottom of 20px;</p>
        </div>
</div>
.container {
  width: 200px;
  background: #f7ce00;
  margin: 40px 0 40px 0;
  overflow: hidden;
}
p {
  padding: 0;
  width: 200px;
  margin: 20px 0 20px 0;
  background-color: #0058b5;
  color: #fff;
}
.newBFC {
  overflow: hidden;
}


새롭게 newBFC를 적용하니 형제들 간의 margin이 더해졌다.

이렇게 새롭게 BFC를 적용하는 것으로 다양한 문제를 해결할 수 있다. 그러나 어떤 방식으로 BFC를 만드냐에 따라 부작용이 발생할 수 있다. 그래서 상황에 맞게 적절히 적용해야 한다.

  • display:table: 반응형에 문제를 줄 수 있다.
  • overflow:scroll: 스크롤바를 생성한다.
  • float:left: 요소를 왼쪽으로 이동시키며 다른 요소들에게 영향을 준다.
  • overflow:hidden: 컨텐츠가 숨겨질 수 있다.

출처 및 참고

좋은 웹페이지 즐겨찾기