[CSS] display 속성의 특징 : box-model

box-model

이번 포스트는 display와 float에 대한 차이점과 활요에 대해 다루도록 하겠습니다. 순서는 다음과 같습니다.

  1. display: block
  2. display: inline
  3. display: inline-block
  4. display: none

위의 4가지를 통틀어 box-model 이라고 합니다.

display: block

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    div{border:1px solid #000;margin:10px;}
    .type2{width:100px;height:100px;}
  </style>
</head>
<body>
  <div>1번 div</div>
  <div class="type2">2번 div</div>
  <div>3번 div</div>
  <div class="type2">4번 div</div>
</body>
</html>

이렇게 div태그는 기본적으로 display:block 속성을 가지고 있습니다. 그리고 display:block이 가지는 특성은 다음과 같습니다.

  • width, height, margin, padding 적용 가능
  • 기본 width가 100%
  • width와 관련 없이 자동 줄바꿈
  • text-align 적용 가능

여기서 주의할 점이 있습니다. 기본적으로 div는 가로너비(width)가 100% 지만, width 속성을 지정하지 않고 margin과 padding을 지정했을 때 이를 포함한 너비가 100%가 됩니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box{width:500px;border:1px solid #000;}
    .box div{padding:20px;margin:20px;background:#ffa;}
  </style>
</head>
<body>
  <div class="box">
    <div>width를 지정하지 않고 margin과 padding을 지정하면?</div>    
  </div>
</body>
</html>

.box div에 width를 지정하지 않은 상태에서는 500px을 벗어나지 못하고 안 쪽으로 margin과 padding이 생기는 모습을 보입니다. 즉, width, margin, padding 전부 합쳐서 500px입니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box{width:500px;border:1px solid #000;}
    .box div{width:100%;padding:20px;margin:20px;background:#ffa;}
  </style>
</head>
<body>
  <div class="box">
    <div>width, margin, padding 지정</div>    
  </div>
</body>
</html>

이렇게 .box div에 width:100%;를 지정하고 난 후에는 width, marign, padding 전부 합쳐서 580px이 됩니다.

이처럼 display:block은 매우 기본적이지만 깊게 생각하지 않으면 "어? 왜 이렇게 되지?" 라고 의문을 갖게 됩니다.

기본 display가 block으로 설정되어 있는 태그는 대표적으로 ol, ul, li, div, header, footer, section, nav, article, p, form, dl, dt, dd, aside 등이 있습니다.

사실 여기서 div 하나만 알고 있어도 무관합니다. li 같은 경우 display:list-item 이지만, 이것도 display:block;과 크게 다르지 않습니다.

display:list-item의 경우 list-style 속성을 적용할 수 있습니다. 하지만 ul, ol, li 태그가 아닌 것에 list-style을 사용하는 웹 페이지는 많지 않습니다.

display: inline

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    span{border:1px solid #000;width:100px;height:100px;margin:5px;padding:5px;}
  </style>
</head>
<body>
  <span>1번 span</span>
  <span>2번 span</span>
  <span>3번 span</span>
  <span>4번 span</span>
</body>
</html>

span은 display:inline; 속성을 가지고 있습니다. (더 정확히는, display 속성을 아예 가지고 있지 않습니다)
눈에 보여지는 것 처럼 inline의 경우 요소들이 가로로 나열됩니다. 더 깊게 이해해 보자면, inline은 스스로 너비를 가지지 못합니다. inline 속성이 가지는 특징은 다음과 같습니다.

  • width, height 적용 불가
  • margin, padding 적용 불가(margin의 가로 여백은 적용됨. 그러나 브라우저 마다 다르다.)
  • width가 없기 때문에 text-align 적용 불가
  • vetical-align 지정 가능 ( inline 요소 중 제일 큰 요소를 기준으로 정렬됨 )
  • inline 요소 하위에 block 요소를 가질 수 없음

inline 요소는 너비와 여백이 적용되지 않습니다. 너비를 가지지 못하기 때문에 width 또한 가질 수 없습니다.



display: inline-block

딱 봐도 display: inline과 block을 합쳐놓은 느낌이 드는 속성입니다. inline-block의 경우 inline과 block의 특징을 모두 가지고 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    div{border:1px solid #000;margin:10px;padding:10px;display:inline-block;}
    .type2{width:100px;height:100px;text-align:right;}
    .box-wrap{text-align:center;width:700px;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div>1번 div</div>
    <div class="type2">2번 div</div>
    <div>3번 div</div>
    <div class="type2">4번 div</div>
  </div>
</body>
</html>

display: inline-block의 특징은 다음과 같습니다.

  • width, height, margin, padding 적용 가능
  • 자동 줄바꿈 되지 않음 => 즉, 가로로 나열됨
  • 가로너비를 지정할 수 있기 때문에 text-align 적용 가능
  • inline-block 요소도 text-align에 영향을 받음, 쉽게 생각해서 inline-block은 너비가 있는 "글자" 라고 생각하면 된다(="글자 처럼 취급" 속성이 적용된 그림 상자)
  • 줄 바꿈이 되지 않기 때문에 vertical-align 적용 가능

보통 inline 대신에 inline-block을 많이 사용합니다. 세로로 나열할 땐 display:block을 사용하고, 가로로 나열할 땐 display:inline-block을 사용하면 되지만, inline-block만 가지곤 가로 나열을 다 커버할 수 없습니다. inline-block이 가지는 고유한 문제점 때문입니다. 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;}
    .box-wrap>div{width:100px;display:inline-block;background:#000;color:#fff;text-align:center;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div>inline-block</div>
    <div>inline-block</div>
    <div>inline-block</div>
    <div>inline-block</div>
    <div>inline-block</div>
  </div>
</body>
</html>

이처럼 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;}
    .box-wrap>div{width:100px;display:inline-block;background:#000;color:#fff;text-align:center;}
  </style>
</head>
<body>
  <div class="box-wrap">
    안
    녕
    하
    세
    요
  </div>
</body>
</html>

즉, 엔터 문자가 공백으로 변환되는 것입니다. 이러한 문제를 해결하기 위한 방법으로 다음과 같은 것들이 있습니다.

엔터 문자를 완전히 삭제한다.

<!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;display:inline-block;background:#000;color:#fff;text-align:center;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div>inline-block</div><div>inline-block</div><div>inline-block</div><div>inline-block</div><div>inline-block</div>
  </div>
</body>
</html>

엔터 문자를 주석처리 한다.

<!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;display:inline-block;background:#000;color:#fff;text-align:center;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div>inline-block</div><!-- 
 --><div>inline-block</div><!-- 
 --><div>inline-block</div><!-- 
 --><div>inline-block</div><!-- 
 --><div>inline-block</div>
  </div>
</body>
</html>

엔터 문자의 폰트 크기를 0으로 한다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .box-wrap{width:500px;border:1px solid #000;font-size:0;}
    .box-wrap>div{width:100px;display:inline-block;background:#000;color:#fff;text-align:center;font-size:15px;}
  </style>
</head>
<body>
  <div class="box-wrap">
    <div>inline-block</div>
    <div>inline-block</div>
    <div>inline-block</div>
    <div>inline-block</div>
    <div>inline-block</div>
  </div>
</body>
</html>

이렇게 세 가지의 방법이 있고, 공통적으로 "공백 문자 제거" 라는 특징을 갖습니다. 얼핏 봐도 굉장히 번거롭게 느껴집니다. 그래서 특별한 경우가 아닌 이상 display:inline-block 대신에 float 속성을 사용합니다.

float에 대한 내용은 다음 포스트에서 다루도록 하겠습니다.



display: none

display: none은 아예 태그를 안보이도록 하는 것입니다. display:none을 이용하여 다음과 같이 요소를 toggle(보이게/안보이게) 처리 할 수 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Layout</title>
  <style>
    .menu>li>ul{display:none;}
    .menu>li:hover>ul{display:block;}
  </style>
</head>
<body>
  * 메뉴에 마우스를 올려보세요
  <ul class="menu">
    <li><a href="#">메인메뉴</a>
      <ul>
        <li><a href="#">서브메뉴</a></li>
        <li><a href="#">서브메뉴</a></li>
        <li><a href="#">서브메뉴</a></li>
      </ul>
    </li>
    <li><a href="#">메인메뉴</a>
      <ul>
        <li><a href="#">서브메뉴</a></li>
        <li><a href="#">서브메뉴</a></li>
        <li><a href="#">서브메뉴</a></li>
      </ul>
    </li>
  </ul>
</body>
</html>





참고링크

다음 링크들에 있는 레이아웃을 만들어보도록 합시다.