[CSS] Float layout에 대한 이해

float-layout

이번 포스트에서는 float layout에 대해 알아보도록 하겠습니다. 포스트의 순서는 다음과 같습니다.





float의 기본속성

float을 이용하면 다음과 같이 레이아웃을 가로로 나열할 수 있습니다.

float: left

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap>div{float:left;width:100px;height:100px;text-align:center;}
    .box1{background:#ffa;}
    .box2{background:#faa;}
    .box3{background:#afa;}
    .box4{background:#aff;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <span>맨 앞의 span</span>
    <div class="box1">1번 div</div>
    <div class="box2">2번 div</div>
    <div class="box3">3번 div</div>
    <div class="box4">4번 div</div>
    <span>맨 뒤의 span</span>
  </div>
</body>
</html>

float: right

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap>div{float:right;width:100px;height:100px;text-align:center;}
    .box1{background:#ffa;}
    .box2{background:#faa;}
    .box3{background:#afa;}
    .box4{background:#aff;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <span>맨 앞의 span</span>
    <div class="box1">1번 div</div>
    <div class="box2">2번 div</div>
    <div class="box3">3번 div</div>
    <div class="box4">4번 div</div>
    <span>맨 뒤의 span</span>
  </div>
</body>
</html>

float: left와 float: right 혼용

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap>div{width:100px;height:100px;text-align:center;}
    .fl{float:left;}
    .fr{float:right;}
    .box1{background:#ffa;}
    .box2{background:#faa;}
    .box3{background:#afa;}
    .box4{background:#aff;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <span>맨 앞의 span</span>
    <div class="box1 fl">1번 div</div>
    <div class="box2 fl">2번 div</div>
    <div class="box3 fr">3번 div</div>
    <div class="box4 fr">4번 div</div>
    <span>맨 뒤의 span</span>
  </div>
</body>
</html>

결과물을 토대로 다음과 같은 특징을 추출할 수 있습니다.

  • 가로로 나열된다.
  • width, height, margin, padding을 지정할 수 있다.
  • width를 지정할 수 있기 때문에 text-align 또한 지정할 수 있다.
  • display:block을 무시한다(추측하자면, inline, inline-block 또한 무시한다고 볼 수 있음)
  • 태그의 순서와 상관 없이 float:left로 지정하면 무조건 왼쪽에 붙는다.
  • 태그의 순서와 상관 없이 float:right로 지정하면 무조건 오른쪽에 붙는다. 이 때, 태그 순서 상 먼저 float:right로 지정한 태그 부터 오른쪽에 붙는다.
  • float 요소과 text 요소가 "어울림" 효과로 보여진다.
어울림 효과에 대한 설명입니다.

이 "어울림" 효과라는 것이 중요합니다. float은 본래 "어울림" 기능으로 만들어졌습니다. 하지만, 가로로 나열할 때 float을 사용 하는 것이 편하다보니 지금은 "어울림" 기능 보단 가로 레이아웃을 만들 때 많이 사용합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap{width:500px;border:1px solid #000;}
    .box-wrap>div{width:100px;height:100px;text-align:center;background:#ffa;}
    .fl{float:left;}
    .fr{float:right;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="fl">어울림</div>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cumque omnis consequuntur vel, aspernatur assumenda. Fuga, aliquid aperiam culpa! Temporibus, sed reiciendis cumque saepe quisquam ipsam vel a at minus illo voluptate provident suscipit sit perferendis vitae, quas voluptatum laboriosam. Eveniet in ipsum, debitis esse obcaecati est veniam magnam sapiente sint?
  </div>
  <div class="box-wrap">
    <div class="fr">어울림</div>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic eligendi doloremque corporis, laudantium ipsam quam blanditiis possimus voluptatem harum cumque vitae sequi eos perspiciatis fuga eius veniam minus accusantium, ratione officiis itaque dolores in reiciendis debitis magni. Magnam fugiat eveniet ab sint, tempore est sit molestias laudantium, ipsa esse repellat.
  </div>
  <div class="box-wrap">
    <div class="fl">어울림1</div>
    <div class="fr">어울림2</div>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia eos, autem nobis eveniet omnis molestias pariatur nisi magnam dignissimos laudantium ipsam, voluptatibus. Ea adipisci eos voluptatem suscipit eveniet blanditiis dolor fugit quae saepe nesciunt neque magnam necessitatibus itaque illo, similique deserunt eius quibusdam modi minus quisquam officiis sequi, placeat in!
  </div>
</body>
</html>

이러한 형태가 본래 float의 기능입니다. 그리고, 이러한 형태로 인하여 야기되는 문제점이 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap{width:500px;border:1px solid #000;border:1px solid #000;}
    .box-wrap>div{width:100px;height:100px;text-align:center;background:#ffa;}
    .fl{float:left;}
    .fr{float:right;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="fl">어울림</div>
    <div class="fl">어울림</div>
    <div class="fl">어울림</div>
    <div class="fl">어울림</div>
    높이가 이상하다 1
  </div>
  높이가 이상하다 2
</body>
</html>

분명 float 요소의 높이는 100px입니다. 하지만 float의 부모 요소는 이를 감지하지 못하고 있습니다. 이게 바로 "어울림" 효과의 부작용입니다. 이것을 해결할 수 있는 것이 clear 속성입니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap{width:500px;border:1px solid #000;border:1px solid #000;}
    .box{width:100px;height:100px;text-align:center;background:#ffa;}
    .fl{float:left;}
    .fr{float:right;}
    .clear{clear:both;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="box fl">어울림</div>
    <div class="box fl">어울림</div>
    <div class="box fl">어울림</div>
    <div class="box fl">어울림</div>
    <div class="clear"></div>
    높이가 정상이다 1
  </div>
  높이가 정상이다 2
</body>
</html>

이렇게 float 뒤에 clear:both를 해주면 어울림 효과가 해제대고, clear를 기준으로 줄바꿈이 됩니다. clear는 이렇든 float을 해제해주는 속성입니다. 하지만 float 뒤에 매번 <div class="clear"></div>를 사용하는 것은 이뻐보이는 코드도 아닐 뿐더러, 비효율적입니다. 그래서 가상선택자인 :after를 이용합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap{width:500px;border:1px solid #000;border:1px solid #000;}
    .box-wrap:after{content:"";display:block;clear:both;}
    .box{width:100px;height:100px;text-align:center;background:#ffa;}
    .fl{float:left;}
    .fr{float:right;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="box fl">어울림</div>
    <div class="box fl">어울림</div>
    <div class="box fl">어울림</div>
    <div class="box fl">어울림</div>
    높이가 정상이다 1
  </div>
  높이가 정상이다 2
</body>
</html>

:before와 :after에는 무조건 content:""; 속성이 들어가야 합니다. 해당 속성이 없으면 :before, :after가 생기지 않습니다. 그리고 display:block을 해줘야 clear:both가 작동합니다.

  • content:"";
  • dispaly:block;
  • clear:both;

이렇게 3가지가 세트입니다. 모르겠으면 외우세요!

float 뒤에는 clear가 온다.

clear는 display:block과 함께 쓰인다.

:before와 :after는 content 속성이 반드시 사용되어야 한다.

결과적으로 :after{content:"";display:block;clear:both;} 는 한 세트다.

float도 생각보다 불편하죠? 나중에 display:flex 속성을 배우면 됩니다! 하지만 flex의 경우 cross browsing 문제가 있습니다. front-end developer는 모든 브라우저와 디바이스에 대한 대응을 해야합니다. 항상 편한 길만 갈 수 있다면 좋겠지만, 언제나 예외는 있는 법! 그렇기 때문에 float와 display에 대한 정확한 이해가 필요합니다.



float과 inline-block의 차이점

float은 "어울림" 이고 inline-block은 "글자처럼취급" 입니다. 이 두가지 특징의 차이를 이해하고 있으면 됩니다. float은 부모에게 "독립적" 인 요소이며, inline-block은 부모에게 "종석적"인 요소입니다. 이 차이는 글자인가 아닌가에서 발생합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap{width:500px;border:1px solid #000;border:1px solid #000;}
    .box-wrap:after{content:"";display:block;clear:both;}
    .box{width:50px;height:50px;text-align:center;background:#ffa;}
    .fl{float:left;}
    .fr{float:right;}
    .ib{display:inline-block;}
    .center{text-align:center;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="box fl">어울림</div>
    Lorem ipsum dolor sit amet, consectetur
    <div class="box fr">어울림</div>
    adipisicing elit. Laboriosam velit, quis eveniet optio earum debitis at porro mollitia maxime officiis recusandae aliquam, ipsum distinctio, culpa natus. Tempore, asperiores
    <div class="box fl">어울림</div>
    assumenda? Aspernatur vitae magnam iste consectetur sit eius, accusantium nihil debitis, autem facere odit. Recusandae harum, dolorem iusto odit eum, voluptate temporibus.
  </div>
  <div class="box-wrap">
    <div class="box ib">글자취급</div>
    Lorem ipsum dolor sit amet, consectetur
    <div class="box ib">글자취급</div>
    adipisicing elit. Laboriosam velit, quis eveniet optio earum debitis at porro mollitia maxime officiis recusandae aliquam, ipsum distinctio, culpa natus. Tempore, asperiores
    <div class="box ib">글자취급</div>
    assumenda? Aspernatur vitae magnam iste consectetur sit eius, accusantium nihil debitis, autem facere odit. Recusandae harum, dolorem iusto odit eum, voluptate temporibus.
  </div>
  <div class="box-wrap">
    <div class="box fl">어울림</div>
    <div class="box fl">어울림</div>
  </div>
  <div class="box-wrap">
    <div class="box ib">글자취급</div>
    <div class="box ib">글자취급</div>
  </div>
  <div class="box-wrap center">
    가운데 정렬
    <div class="box fl">어울림</div>
    <div class="box fl">어울림</div>
  </div>
  <div class="box-wrap center">
    가운데 정렬
    <div class="box ib">글자취급</div>
    <div class="box ib">글자취급</div>
  </div>
</body>
</html>

float

  1. text의 크기와 상관 없이 섞인다.
  2. float 요소 자체는 text-align의 영향을 받지 않는다.
  3. float 요소들 사이에 있는 글자, 공백을 무시하고 정렬된다.
  4. float 요소를 clear를 해주지 않으면, float 요소의 부모의 높이가 이상해질 수 있다. 즉, 레이아웃이 흐트러질 수 있다.

inline-block

  1. text와 나란히 나열된다.
  2. inline-block 요소 자체가 text-align의 영향을 받는다.
  3. inline-block 요소들 사이에 있는 글자, 공백과 나란히 정렬된다.
  4. inline-block 요소는 clear줄 필요 없다. 즉, inline-block 요소들 사이에 있는 공백만 잘 제거한다면 레이아웃이 흐트러지지 않는다.




float과 inline-block을 같이 사용하기

float과 inline-block으로 box-list를 이용하여 가운데 정렬 되는 메뉴를 만들어보도록 하겠습니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    *{margin:0;padding:0;}
    ul,li{list-style:none;}
    a{text-decoration:none;}
    .menu{width:500px;text-align:center;border:1px solid #000;}
    .menu>nav{display:inline-block;vertical-align:middle;}
    .menu a{display:block;}
    .menu>nav>ul:after{content:"";display:block;clear:both;}
    .menu>nav>ul>li{float:left;}
    .menu>nav>ul>li+li{margin-left:1px;}
    .menu>nav>ul>li>a{width:100px;padding:10px;background:#09F;color:#fff;}
    .menu>nav>ul>li>ul{display:none;}
    .menu>nav>ul>li:hover>a{background:#06F;}
    .menu>nav>ul>li:hover>ul{display:block;}
    .menu>nav>ul>li>ul a{background:#09F;color:#fff;padding:5px 0;}
    .menu>nav>ul>li>ul a:hover{background:#06F;}
  </style>
</head>
<body>
  <div class="menu">
    <nav>
      <ul>
        <li><a href="#">메뉴01</a>
          <ul>
            <li><a href="#">메뉴0101</a></li>
            <li><a href="#">메뉴0102</a></li>
            <li><a href="#">메뉴0103</a></li>
          </ul>
        </li>
        <li><a href="#">메뉴02</a>
          <ul>
            <li><a href="#">메뉴0201</a></li>
            <li><a href="#">메뉴0202</a></li>
            <li><a href="#">메뉴0203</a></li>
          </ul>
        </li>
        <li><a href="#">메뉴03</a>
          <ul>
            <li><a href="#">메뉴0301</a></li>
            <li><a href="#">메뉴0302</a></li>
            <li><a href="#">메뉴0303</a></li>
          </ul>
        </li>
      </ul>
    </nav>
  </div>
</body>
</html>

위의 소스에 사용된 기법들은 다음과 같습니다.

  • 가상선택자 :after, :hover
  • a태그에 display:block을 지정 => width, height, margin, padding 사용
  • 친구 선택자 + => 2번째 li 부터 margin-left: 1px 지정
  • block 요소에 text-align:center 후 inline-block을 가운데 정렬 시킴
  • inline-block 밑에 float 요소로 가로 나열

이러한 것들을 이용하여 가운데로 정렬되는 2depth 메뉴를 만들었습니다.

참고링크