Float

float란?

요소를 좌, 우 방향으로 띄운다. 가장 오래된 방법이고 번거롭지만 아직도 실무에서 많이 쓰이는 방법이니 잘 숙지해두자.

float란, 물체를 3차원적으로 위로 띄우는 개념이다. 상자 A,B,C,D가 있다고 가정해보자.
A {float:left;}를 설정하면 A상자가 위로 뜨면서 B상자는 A상자 아래로 들어간다.
(이때, B상자에 있는 텍스트는 가려지지 않고 A상자 옆으로 보이게 되는데 만약 B상자의 width가 A상자보다 크다면 B상자가 옆으로 이동한 것처럼 보이게 된다.)
float설명1
float2

float의 사용방법

요소에 float 속성을 적용하면, 적용된 요소 주변으로 문자가 흐른다. 즉, {float:left;}를 적용하면 적용한 요소의 오른쪽으로 다음 요소가 배치된다.
예를 들어 설명해보자.

스크린샷 2020-07-28 오전 10 09 43

이러한 모양의 레이아웃을 만든다고 가정하자.

박스들을 옆으로 배치하기 위해 박스들에게 {float:left;}를 사용했다.
스크린샷 2020-07-28 오전 10 09 57
박스들이 레이어 되면서 박스들의 부모인 container가 높이를 잃어버리고 부분이 위로 올라오게 된다.
(여기서 side가 박스 옆으로 배치됐다고 오해할 수 도 있는데 side의 가로 너비가 더 커서 옆으로 삐져나왔을 뿐 옆으로 배치된 것은 아니다.)
그러면 를 박스 아래로 배치시킬 수 있는 방법이 뭐가 있을까?
레이어된 박스들의 높이를 읽어들이려면 float 속성을 해제해야한다. 다양한 float 해제 방법을 알아보자.

float을 해제하는 방법

float을 해제하는 방법에는 세가지가 있다.
1)가상 요소 선택자 ::after 사용 (추천!)
2)다음 형제 요소에 {clear: both;} 추가
3)부모 요소에{overflow:hidden}, {overflow:none;}추가

  1. ::after를 추가하는 방법을 자세히 살펴보자
    이 방법은 가상 요소 선택자 ::after를 사용해서 float를 해제하는 방법이다. 박스 요소 이후 float를 해제해주는 가상의 컨텐츠를 만들어 박스 이후부터는 float가 해제되게 해주는 방법이다.
    ::after로 어떤 속성을 삽입해야 하는지 알아보도록 하자.
    .container::after {
      content:"";
      clear:both;
      display:block;
                  }
    (클래스 이름이 container인 이유는 박스들의 부모 요소의 이름이 container이기 때문이다.)
    코드 한줄한줄 해석해보도록 하자.
    먼저, content:""; 는 가상요소 선택자를 사용할 때 필수적으로 입력해줘야 하는 값이다. (“필수적”이라는 단어를 사용했지만 이미 컨텐츠가 존재하고 가상요소 선택자로 해당 컨텐츠를 꾸며주려고 할때는 생략해도 된다. float해제를 위해 사용할때는 필수적으로 작성해줘야 한다.)
    {clear:both;}는 말 그대로 float를 clear해준다. 이것을 사용해주면 float를 해제해주고 레이어된 요소의 높이값을 읽어들인다.
    {display:block;} 가상 요소 선택자는 inline 속성의 컨텐츠를 만들어내는데, clearfix는 block 상태일때만 적용이 가능하다. 꼭 block일 필요는 없고 {display:table;}도 가능하다.

앞에서

.container::after {
     content:"";
     clear:both;
     display:block;
                 }

클래스명 뒤에 ::after를 추가해줬는데 레이아웃 잡을때 float를 사용할 일이 굉장히 많을 수 있다. 그럴때마다 clear가 필요한 클래스명뒤에 ::after를 붙이고 위의 코드를 작성하면 같은 코드가 여러번 반복되는 일이 생긴다.
따라서,

.clearfix::after {
     content:"";
     clear:both;
     display:block;
                 }

clearfix라는 이름의 클래스 명으로 코드를 작성하고 clearfix가 필요한 부분의 클래스 이름에 clearfix를 추가해준다. 이런 방법으로 하면 불필요한 코드를 줄일 수 있다.

<div class="container clearfix">
  1. 형제 요소에 {clear: both;} 추가 방법을 알아보자
    이 방법은 float을 사용하는 요소 다음의 형제 요소에 {clear: both;}를 적어준다. 간단하지만 만약에 float을 사용하는 요소 다음에 형제 요소가 없다면 의미없는 태그를 넣어 해제해야 하기 때문에 권장하지 않는다.
    {clear: both;}의 문제점은 한가지 더 있는데, 위의 예제에서 박스의 부모요소의 height를 auto로 설정하고 박스들에 float:left; 처리하고 side에 해제해준다.
    그 결과는, 이렇게 나온다.

    형제 요소 문제점

    여기까지는 별 문제가 없어보인다. 그런데, 만약 side와 박스가 너무 가깝다고 생각해 side에 margin-top:10px;을 걸어주면 변화가 없다.
    왜 그럴까?
    앞서 설명한 float 개념에 따르면 boxA,B,C는 공중에 붕 떠있고 side는 박스들이 떠있는 곳 바로 아래에 깔려 있게된다. 이때, clear로 side의 float을 해제해 준다면 side는 박스 요소의 높이만큼의 마진을 가지고 내려온다. 이미 마진을 가진 상황에서 추가로 {margin-top:10px;}을 준다면 마진 병합 현상이 일어나 반영이 되지 않는 것이다.
    이를 해결하려면 마진 병합을 고려해서 계산한 값을 넣어주거나 clearfix로 해결해야하는 번거로움이 있다.

    3){overflow:hidden;} 방법
    float를 쓰려는 요소의 부모(여기서는 container)에 {overflow:hidden;}을 추가해준다.
    방법은 간단하지만 레이어된 박스의 높이값을 읽어들이는 것과 overflow는 무슨 관련이 있는걸까?
    정답은 BFC와 관련이 있다.
    BFC는 간단하게 설명하자면 레이아웃 안의 레이아웃이다. 조금 더 쉽게 설명하자면 자체적인 공간을 만들어내고 이 공간안에 있는 내용들을 랜더링한다(읽어들인다). 몇가지 속성들이 BFC를 만들어낸다.
    overflow를 예를 들어 풀어 설명하자면, overflow는 BFC를 생성해내는데, 이는 overflow를 부여받은 요소안에 공간을 만들어내고 이 공간은 요소의 자식 컨텐츠들을 읽어내린다. 레이어된 자식컨텐츠들을 읽어내면서 높이값도 찾게 되고 이로 인해 float를 해제한 것처럼 보이게 된다.
    BFC를 만들어내는 속성값들이 몇가지 있는데 다음의 md에서 자세히 설명하도록 하겠다.
    덧붙여, 이 방법을 사용하지 않는 이유는 overflow:hidden;은 float를 해제하기 위한 속성이 아니기 때문에 이 코드를 왜 작성했는지 직관적으로 알기 힘들다. 또, float가 나올때마다 작성해줘야 하기 때문에 성능면에서도 효율적이지 못하다.

    ++++
    float 해제 방법에 대해서 길게 설명했지만 가장 중요한 것은 float 속성 그 자체이다.
    float를 사용할때 이것이 가진 속성을 간과하고 사용해 애를 먹을 때가 많은데 잘 알아두도록 하자.

    1. float 했을때 컨텐츠 크기만큼의 너비를 가진다.

    만약, width를 정해주지 않은 공간을 float 시킨다고 가정해보자.
    width를 정해주지 않는다면 해당 영역은 콘텐츠 영역만큼의 width만 가져가게 된다.
    예를 들어, normal flow일 경우,(아직 float 시키지 않았을 경우)

    <div>동해물과 백두산이</div>

    이 영역의 width는 100%(뷰포트 전체 너비)일 것이다. 이 영역을 Float 시키면 width는 [동해물과 백두산이]에 해당하는 width만 차지하며 레이어 된다.
    이러한 속성은 “고정형 레이아웃 구현 week2”의 term-list 작성 부분에서 경험했었다.

  2. float시켰을 때 항상 앞의 요소 옆으로 붙는 것은 아니다.

만약, boxA,B(둘다 block)가 있다고 치자.
여기서, boxB를 float:left시켰다. 그러면 B는 어디로 배치될까? 여기서 boxA 옆으로 배치된다고 생각하기 쉽다.
그러나, boxA는 현재 블록 상태로 width를 100% 가지고 있기 때문에 boxB가 갈 수 있는 자리가 없다. 따라서 이경우 boxB는 원래 자기 자신의 자리에서 레이어 되어 있다.
스크린샷 2020-07-28 오전 10 54 21

이 특성을 잘 기억하고 나중에 조심하도록 하자.
혹시 잊었다면 term-list 부분을 다시 한번 구현해보도록 한다.