[CSS] float 와 overflow의 관계 그리고 BFC(Block Formatting Context)

Narcoker·2023년 6월 3일
0

CSS

목록 보기
36/40

overflow

자식의 크기가 부모 요소보다 커서
자식이 부모 요소의 범위를 벗어났을 때 처리할 방법을 지정하는 속성이다.

float

자식 요소가 부모의 배치 흐름으로 부터 빠져나온다.
이때 이 요소는 텍스트 및 inline 요소가 본인에 좌우측을 따라 배치되어야 함을 지정한다.
-MDN 발췌-

인강에 따르면 float 가 적용된 요소는 묵시적으로 inline-block 요소가 된다고 한다.

정확하게는 BFC 요소가 되는 것이다. BFC는 아래에서 설명한다.

자식요소(div.parent > div.child)에 float 속성 적용 전,

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>float & overflow</title>
    <style>
      * {
        box-sizing: border-box;
      }
      body {
      	background-color: #eee
      }
      .parent {
        width: 600px;
        border: 5px solid red;
      }
      .child {
        background-color: royalblue;
        border-radius: 12px;
        text-align: center;
        color: white;
      }
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="child">child</div>
    </div>
  </body>
</html>

자식요소(div.parent > div.child)에 float 속성 적용 후, inline-block이 된 모습

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>float & overflow</title>
    <style>
      * {
        box-sizing: border-box;
      }
      body {
      	background-color: #eee
      }
      .parent {
        width: 600px;
        border: 5px solid red;
        background-color: white;
      }
      .child {
        background-color: royalblue;
        border-radius: 12px;
        text-align: center;
        color: white;
      }
      .float-left {
        float: left;
      }
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="child float-left">child</div>
    </div>
  </body>
</html>

이상한 점을 발견할 수 있다.

부모요소 (div.parent)의 범위가 줄어들었다.
위에서 언급했던 자식 요소가 부모의 배치 흐름으로 부터 빠져나온다.
의미를 이 부분에서 확인할 수 있다.

부모 요소에 크기를 지정하지 않으면 자식의 크기에 알맞게 알아서 증가한다.
현재는 width 만 지정되어있고 height는 지정되어있지 않다.

즉, 부모 요소는 float 속성이 적용된 자식요소의 범위를 취급하지 않는다.

이를 확인하기 위해서 child의 모양과 크기를 변경하고
float 속성이 적용되지 않은 span 자식을 추가해보겠다.

부모요소는 float 속성이 적용되지 않은
span 자식요소의 범위만 취급해서 부모요소의 범위가 커진 모습을 확인할 수 있다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>float & overflow</title>
    <style>
      * {
        box-sizing: border-box;
      }
      body {
      	background-color: #eee
      }
      .parent {
        width: 600px;
        border: 5px solid red;
      	background-color: white;
      }
      .child {
        background-color: royalblue;
        border-radius: 12px;
        text-align: center;
        color: white;
      }
      .float-left {
        float: left;
      }
      .circle {
        width: 200px;
        height: 200px;
        border-radius: 50%;
        text-align: center;
        line-height: 200px;
      }
      .orange {
        background-color: orange;
      }
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="circle child float-left">child</div>
      <span class="orange child">span</span>
    </div>
  </body>
</html>

인강에서 듣기로는 이러한 현상을 해결하기 위해서
부모요소에 overflow: hidden 을 추가하거나
height 를 지정하면 된다고 한다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>float & overflow</title>
    <style>
	   /* 생략 */
      .parent {
        width: 600px;
        border: 5px solid red;
        overflow: hidden;
      }
  	  /* 생략 */
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="circle child float-left">child</div>
      <span class="orange child">span</span>
    </div>
  </body>
</html>

왜 하필 overflow 속성 일까?

맨 처음에 말했던 것처럼
overflow의 본 목적은 스크롤 기능을 부여하거나 가리거나 하는 등
부모요소의 범위를 넘어간 자식요소를 어떻게 할지 지정하기 위함이다.

overflowfloat 이슈를 해결하기 위해 존재하는 것이 아닌데
왜 여기서 사용하는가?

강사도 이유에 대해서 설명해주지 않았다.

조사한 바에 따르면 CSS의 BFC(Block Formatting Context)와 관련이 있다고 한다.

BFC(Block Formatting Context)

웹 페이지를 렌더링하는 시각적 CSS의 일부로서,
블록 박스의 레이아웃이 발생하는 지점과 float 요소의 상호작용 범위를 결정하는 범위이다.
-MDN 발췌-

내가 이해한 대로 설명하자면 BFC 요소는 float 요소인 자식의 범위도 취급한다는 말인 것 같다.
즉, 새로운 문서(블록 혹은 body 혹은 html)을 만들어낸다는 것이다.

최상위 태그인 html태그가 BFC 요소라고 한다.

이를 확인하기 위해서 bodyfloat 속성을 추가해봤다.
html 라는 부모요소에는 body 자식 하나 밖에 없기 때문에
자식 요소의 범위를 취급하지 않아야한다.

html 태그의 자식요소로 head 태그도 있지 않냐 하는데
head 태그는 문서의 메타데이터를 담는 공간으로, 랜더링 되지 않는다.

확실한 확인을 위해서
body 태그의 background-color를 잠깐 yellow로 변경하고
float: left 를 지정했다.

htmlfloat 요소인 body 를 인식하고 배경색이 출력되는 것을 확인할 수 잇다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>float & overflow</title>
    <style>
	   /* 생략 */
      body {
        background-color: yellow;
      	float: left;
      }
      .parent {
        width: 600px;
        border: 5px solid red;
      	background-color: white;
        overflow: hidden;
      }
  	  /* 생략 */
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="circle child float-left">child</div>
      <span class="orange child">span</span>
    </div>
  </body>
</html>

여기서 또 이상한 점을 발견할 수 있다.

body 요소에 widthheight를 지정하지 않았는데
parentwidthheight를 벗어나서
뷰포트 전체에 background-color: yellow 가 지정이 되는가?

특수한 요소 body, html

결론부터 말하자면 bodybackground
루트 요소인 html 태그가 background 속성이 존재하지 않을 때
bodybackgroundhtml에 전달한다.

CSS의 목적은 안정적인 레이아웃을 쉽게 만들기 위함이다.
이 목적을 달성하기 위해 의도적으로 이렇게 만들었다고 한다.

이를 확인하기 위해서 bodyborder: 10px solid greenpadding: 20px을 추가해보겠다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>float & overflow</title>
    <style>
	   /* 생략 */
      body {
        background-color: yellow;
      	float: left;
        border: 10px solid green;
        padding: 20px;
      }
  	  /* 생략 */
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="circle child float-left">child</div>
      <span class="orange child">span</span>
    </div>
  </body>
</html>

관례 상 html 태그에는 background 속성을 넣지 않지만
사실 확인을 위해서 html 태그에 background-color 속성을 추가해보겠다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>float & overflow</title>
    <style>
	   /* 생략 */
      html{
        background-color: blueviolet;
      }
      body {
        background-color: yellow;
      	float: left;
        border: 10px solid green;
        padding: 20px;
      }
  	  /* 생략 */
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="circle child float-left">child</div>
      <span class="orange child">span</span>
    </div>
  </body>
</html>

그래서 왜 overflow를 사용하는가?

overflow 속성을 지정하면 그 요소는 BFC 요소가 되기 때문이다!!!

그렇기 때문에 부모요소에 overflow 속성을 지정하면
float인 자식들을 자신의 범위로 취급하고 이에 따라 범위가 늘어나는 것이다.

Default BFC 요소와 BFC 요소를 만드는 다른 방법

Default BFC 요소

문서의 루트요소인 html 태그

BFC 요소를 만드는 다른 방법

float 속성 지정

position : absolute | fixed
절대 위치를 지정

display : inline-block | flex | flex-inline | grid | inline-grid 지정

overflow 속성 값이 visible 이외의 값 으로 지정

display : flow-root 지정

이외의 빙밥은 다음 링크에서 참조
https://developer.mozilla.org/ko/docs/Web/Guide/CSS/Block_formatting_context

overflow의 의미적 문제 -> display: flow-root 사용 권장

overflow의 본 목적은 float 인 요소를 제어하기 위함이 아니다.
문제 해결은 할 수 있지만 overflow: hidden 으로 작성된 코드를
이후에 다른 개발자가 본다면 의도를 파악하기 힘들 가능성이 있다.

MDN에 따르면 float 범위 문제 현상은
display: flow-root 을 지정하여 해결하라고 권장하고 있다.

flow-root 말 그대로 이 요소는 문서의 시작을 의미하기 때문이다.

BFC 의 두번째 용도, 마진 겹침/상쇄 현상 중 '상쇄' 해결

마진 겹침/상쇄 현상에 대해 먼저 설명하겠다.

마진 겹침/상쇄 현상이 발생하는 코드이다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>margin problem</title>
    <style>
      .parent {
        background-color: lightblue;
        width: 140px;
      }
      .child {
        width: 100px;
        height: 100px;
        background-color: white;
        margin: 20px;
      }
      .row {
        display: flex;
      }
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="child">child 1</div>
      <div class="child">child 2</div>
    </div>
  </body>
</html>

child 상하좌우에 margin: 20px 을 부여했다.

이상한 점 2가지를 확인할 수 있다.

  1. child 1margin-top: 20px 이고 child 2margin-bottom: 20px 이니
    child 들 사이의 공간은 총 40px 이어야하는데 20px 만 적용되었다. (겹침)
  1. child 1 상단과 child 2하단에 margin이 적용되지 않았다. (상쇄)

case 1 : 겹침

겹침 현상의 경우 CSS의 의도된 동작이라고 한다.
단, 상하 요소에서만 발생한다. 좌우에서는 겹침 현상이 발생하지 않는다.

이 또한 CSS의 목적을 달성하기 위해 의도적으로 이렇게 만들었다고 한다.

모든 margin을 삭제하고
child 1 에는 margin-bottom: 20px,
child 2 에는 margin-top: 40px 을 줘서
사이 margin 값이 다를 때도 겹침 현상이 일어나는지 실험해봤다.

case 2 : 상쇄

최상단 자식의 margin-top과 최하단 자식의 margin-bottom이 상쇄되는 현상이다.
논리대로라면 20px 씩 부여되어야한다.

이를 해결하기 위해서 부모요소를 BFC 요소로 만들어준다.
W3C 에 따르면 BFC는 이 현상을 해결하기 위한 용도라고 한다.

BFC 요소의 높이 계산 알고리즘은
최상단 요소의 margin-top-edge - 최하단 요소의 margin-bottom-edge
구현되어 있기 때문이다.

만약 모든 자식이 inline 요소일 경우 inline 요소의 최상/하단 을 기준으로 계산된다고 한다.

https://www.w3.org/TR/CSS2/visudet.html

참고

profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글