박스 모델과 요소 배치
지난 장에서 우리는 CSS를 이용해 웹 페이지의 색상, 폰트, 텍스트 스타일을 섬세하게 조절하는 방법을 배웠습니다. 이제 HTML 요소들이 화면에 어떻게 배치되고 공간을 차지하는지에 대한 근본적인 원리인 CSS 박스 모델(Box Model) 을 이해할 차례입니다. 웹 페이지의 모든 HTML 요소는 기본적으로 사각형의 '박스(Box)' 형태로 존재하며, 이 박스들이 어떻게 상호작용하고 공간을 차지하는지를 이해하는 것은 웹 레이아웃을 정확하게 제어하는 데 필수적입니다.
이 장에서는 CSS 박스 모델의 구성 요소들을 자세히 살펴보고, 각 요소의 크기와 여백을 제어하는 다양한 CSS 속성들을 학습할 것입니다. 또한, HTML 요소들이 기본적으로 화면에 어떻게 배치되는지, 그리고 이 배치 방식을 제어하는 display
속성에 대해서도 알아보겠습니다. 이 지식은 복잡한 웹 레이아웃을 구현하기 위한 단단한 기반이 될 것입니다.
CSS 박스 모델: 모든 HTML 요소는 상자다!
웹 페이지의 모든 HTML 요소는 박스 모델이라는 개념을 기반으로 렌더링됩니다. 즉, 여러분이 본 모든 div
, p
, img
, a
태그는 화면에서 보이지 않는 사각형 박스로 둘러싸여 있다고 생각할 수 있습니다. 이 박스 모델은 콘텐츠, 패딩, 테두리, 마진이라는 네 가지 주요 구성 요소로 이루어져 있습니다.
박스 모델의 구성 요소
-
콘텐츠(Content)
- 텍스트, 이미지, 비디오 등 요소의 실제 내용이 들어가는 영역입니다.
width
와height
속성으로 이 콘텐츠 영역의 크기를 조절합니다.
-
패딩(Padding)
- 콘텐츠 영역과 테두리(Border) 사이의 여백입니다. 마치 액자 속 그림 주변의 매트와 같습니다.
- 패딩은 배경색(
background-color
)의 영향을 받습니다. - 속성:
padding-top
,padding-right
,padding-bottom
,padding-left
: 각 방향의 패딩을 개별적으로 설정합니다.padding
: 상하좌우 모든 방향의 패딩을 한 번에 설정하는 단축 속성입니다.padding: 10px;
(모든 방향 10px)padding: 10px 20px;
(상하 10px, 좌우 20px)padding: 10px 20px 30px;
(상 10px, 좌우 20px, 하 30px)padding: 10px 20px 30px 40px;
(상 10px, 우 20px, 하 30px, 좌 40px - 시계 방향)
-
테두리(Border)
- 패딩과 마진(Margin) 사이의 선입니다. 콘텐츠와 패딩을 둘러싸는 경계선 역할을 합니다.
- 속성:
border-width
: 테두리의 두께border-style
: 테두리의 스타일 (solid
,dotted
,dashed
,double
등)border-color
: 테두리의 색상border
: 위의 세 속성을 한 번에 설정하는 단축 속성입니다.border: 1px solid black;
(1px 두께, 실선, 검정색)
- 각 방향별 속성도 있습니다:
border-top
,border-right
,border-bottom
,border-left
-
마진(Margin)
- 테두리(Border) 바깥쪽의 여백입니다. 요소와 요소 사이의 간격을 조절하는 데 사용됩니다.
- 마진은 배경색의 영향을 받지 않고 투명합니다.
- 속성:
margin-top
,margin-right
,margin-bottom
,margin-left
: 각 방향의 마진을 개별적으로 설정합니다.margin
: 상하좌우 모든 방향의 마진을 한 번에 설정하는 단축 속성입니다. (패딩과 동일한 방식)margin: 20px;
(모든 방향 20px)margin: 0 auto;
(좌우 마진을 자동으로 설정하여 블록 요소를 가로로 중앙 정렬할 때 사용, 상하 마진은 0)
box-sizing
속성: 계산 방식 변경
CSS 박스 모델의 기본 계산 방식은 width
와 height
가 콘텐츠 영역만을 의미합니다. 따라서 패딩과 테두리를 추가하면 요소의 실제 크기가 지정한 width
/height
보다 커집니다. 이는 레이아웃 계산을 어렵게 만들 수 있습니다.
box-sizing
속성은 이러한 계산 방식을 변경합니다.
-
content-box
(기본값)width
,height
는 콘텐츠 영역만을 의미합니다.- 실제 요소의 너비 =
width
+padding-left
+padding-right
+border-left-width
+border-right-width
-
border-box
width
,height
가 패딩과 테두리를 포함한 영역을 의미합니다. 콘텐츠 영역은 이 값에서 패딩과 테두리를 뺀 나머지입니다.- 이 방식은 레이아웃을 만들 때 요소의 실제 크기를 예측하기 훨씬 쉬워 현대 웹 개발에서 널리 사용됩니다.
- 강력 권장: 대부분의 CSS 프레임워크나 최신 프로젝트에서는
* { box-sizing: border-box; }
를 사용하여 모든 요소의 박스 모델을border-box
로 설정하고 시작합니다.
/* 모든 요소에 border-box 적용 */ * { box-sizing: border-box; } .my-box { width: 200px; height: 100px; padding: 20px; border: 5px solid blue; /* content-box일 경우 실제 너비: 200 + 20*2 + 5*2 = 250px border-box일 경우 실제 너비: 200px (패딩과 보더가 200px 안에 포함됨) */ }
display
속성: 요소의 기본 배치 방식
모든 HTML 요소는 기본적으로 display
라는 속성을 가지고 있으며, 이 속성 값에 따라 웹 페이지에 어떻게 나타나고 공간을 차지하는지가 결정됩니다. CSS를 사용하여 이 display
속성 값을 변경함으로써 요소의 배치 방식을 제어할 수 있습니다.
블록(Block) 요소
-
항상 새로운 줄에서 시작합니다.
-
부모 요소의 가로 너비(100%)를 기본적으로 모두 차지합니다. (가능한 최대 너비)
-
width
,height
,margin
,padding
,border
속성을 모두 사용할 수 있습니다. -
예시:
<div>
,<h1>
~<h6>
,<p>
,<ul>
,<li>
,<form>
,<header>
,<footer>
,<section>
,<article>
,<aside>
등div { background-color: lightblue; width: 200px; /* 너비를 지정해도 새로운 줄에서 시작 */ height: 100px; margin-bottom: 10px; /* 마진 적용 가능 */ }
인라인(Inline) 요소
-
새로운 줄에서 시작하지 않고, 콘텐츠의 흐름에 따라 이전 요소 바로 옆에 배치됩니다.
-
콘텐츠의 너비만큼만 공간을 차지합니다.
-
width
,height
속성은 적용되지 않습니다. (콘텐츠 크기에 따라 결정됨) -
margin-top
,margin-bottom
,padding-top
,padding-bottom
은 적용되지만, 다른 인라인 요소에 영향을 주지 않으므로 시각적인 효과가 제한적입니다. (margin-left
,margin-right
,padding-left
,padding-right
는 정상 적용) -
예시:
<span>
,<a>
,<strong>
,<em>
,<img>
,<input>
,<label>
등span { background-color: lightgreen; padding: 5px; /* 좌우 패딩은 적용 */ margin-right: 5px; /* 좌우 마진은 적용 */ /* width, height는 적용되지 않음 */ }
💡 주의:
<img>
태그는 인라인 요소이지만width
와height
속성이 적용됩니다. 이는img
가 콘텐츠 자체의 고유한 크기를 가지기 때문입니다. 하지만 기본적으로는 텍스트 흐름에 따라 배치됩니다.
인라인-블록(Inline-Block) 요소
-
인라인 요소처럼 새로운 줄에서 시작하지 않고 콘텐츠 흐름에 따라 배치됩니다.
-
블록 요소처럼
width
,height
,margin
,padding
,border
속성을 모두 자유롭게 적용할 수 있습니다. -
인라인과 블록의 장점을 결합한 형태입니다.
-
적용 방법:
display: inline-block;
.card { display: inline-block; /* 옆으로 나열되면서 */ width: 150px; /* 너비와 높이 지정 가능 */ height: 180px; background-color: #f0f0f0; margin: 10px; /* 마진도 자유롭게 */ padding: 15px; border: 1px solid #ddd; }
💡 활용: 메뉴 항목 (
<li>
), 버튼, 작은 카드 형태의 UI 요소 등을 가로로 나열하면서도 개별적인 크기나 여백을 제어해야 할 때 매우 유용합니다.
display: none;
-
요소를 완전히 숨기고, 공간도 차지하지 않도록 합니다. 화면에서 완전히 제거된 것처럼 동작합니다.
-
스크린 리더 등 보조 기술에서도 이 요소를 읽지 않습니다.
-
참고:
visibility: hidden;
은 요소를 숨기지만, 공간은 그대로 차지합니다..hidden-element { display: none; /* 요소가 보이지 않고 공간도 차지하지 않음 */ } .invisible-element { visibility: hidden; /* 요소는 보이지 않지만 공간은 차지함 */ }
마진 상쇄(Margin Collapsing) 현상 (심화)
블록 요소의 수직 마진(top-margin, bottom-margin)은 때때로 흥미로운 방식으로 동작합니다. 인접한 두 블록 요소의 수직 마진이 겹칠 때, 두 마진 중 더 큰 값 하나만 적용되는 현상을 마진 상쇄(Margin Collapsing) 또는 마진 병합이라고 합니다.
-
적용되는 경우
- 형제 요소 간의 상하 마진: 위 요소의
margin-bottom
과 아래 요소의margin-top
이 만날 때. - 부모-자식 요소 간의 상하 마진: 부모 요소의
margin-top
과 첫 번째 자식 요소의margin-top
이 겹칠 때 (패딩이나 보더로 분리되지 않은 경우). - 빈 블록 요소의 상하 마진: 패딩, 보더, 콘텐츠가 없는 빈 블록 요소의
margin-top
과margin-bottom
이 겹칠 때.
- 형제 요소 간의 상하 마진: 위 요소의
-
예시
<div style="margin-bottom: 20px; background-color: lightcoral;">첫 번째 박스</div> <div style="margin-top: 30px; background-color: lightgreen;">두 번째 박스</div>
마진 상쇄는 CSS 레이아웃을 예측하기 어렵게 만들 수 있지만, 의도된 디자인 패턴이며 특정 상황에서 요소 간의 불필요한 간격을 줄여줍니다. 마진 상쇄를 피하려면
padding
이나border
를 추가하거나,display: flex
또는display: grid
와 같은 새로운 레이아웃 방식을 사용하면 됩니다.
실습: 박스 모델과 display
속성 활용
지금까지 배운 박스 모델과 display
속성들을 활용하여 간단한 제품 목록 페이지를 만들어 봅시다.
-
프로젝트 폴더 구조
web-dev-practice/ ├── products.html └── css/ └── product.css
-
products.html
파일 작성products.html <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>박스 모델과 Display 실습 - 제품 목록</title> <link rel="stylesheet" href="css/product.css"> </head> <body> <header> <h1>우리 가게 인기 상품</h1> <p>다양한 제품을 만나보세요!</p> </header> <main> <div class="product-grid"> <div class="product-item"> <img src="https://via.placeholder.com/150x150?text=Product+A" alt="제품 A 이미지"> <h3>멋진 제품 A</h3> <p>이 제품은 정말 멋집니다. 한 번 사용해 보세요!</p> <span class="price">25,000원</span> <a href="#" class="buy-button">구매하기</a> </div> <div class="product-item"> <img src="https://via.placeholder.com/150x150?text=Product+B" alt="제품 B 이미지"> <h3>매력적인 제품 B</h3> <p>당신을 더욱 빛나게 할 아이템입니다.</p> <span class="price">40,000원</span> <a href="#" class="buy-button">구매하기</a> </div> <div class="product-item"> <img src="https://via.placeholder.com/150x150?text=Product+C" alt="제품 C 이미지"> <h3>실용적인 제품 C</h3> <p>일상에 편리함을 더해줄 제품!</p> <span class="price">15,000원</span> <a href="#" class="buy-button">구매하기</a> </div> </div> <div class="info-section"> <p>더 많은 제품 정보는 <a href="#">여기</a>를 클릭하세요.</p> <span class="contact-info">문의: support@ourshop.com</span> <span class="notice-info">공지사항: 배송 지연 안내</span> </div> </main> <footer> <p>© 2025 우리 가게. 모든 권리 보유.</p> </footer> </body> </html>
-
css/product.css
파일 작성css/product.css /* 모든 요소에 border-box 적용하여 박스 모델 계산 용이하게 함 (강력 권장) */ * { box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; background-color: #f4f7f6; color: #333; line-height: 1.6; } /* 헤더 스타일 */ header { background-color: #4CAF50; /* 초록색 */ color: white; text-align: center; padding: 30px 20px; margin-bottom: 30px; /* 헤더 아래 여백 */ box-shadow: 0 4px 8px rgba(0,0,0,0.1); } header h1 { font-size: 2.8em; margin-bottom: 10px; /* h1 아래 여백 */ } header p { font-size: 1.2em; margin: 0; /* p 태그 기본 마진 제거 */ } /* 메인 콘텐츠 영역 */ main { max-width: 1000px; margin: 0 auto 50px auto; /* 좌우 auto로 중앙 정렬 */ padding: 20px; } /* 제품 그리드 (세로 정렬된 블록 요소들) */ .product-grid { display: flex; /* Flexbox는 다음 장에서 자세히 배우지만, 여기서는 요소들을 가로로 배치하는 데 사용 */ flex-wrap: wrap; /* 요소들이 공간이 부족하면 다음 줄로 넘어가도록 함 */ justify-content: center; /* 가로 중앙 정렬 */ gap: 30px; /* 요소들 사이의 간격 */ margin-bottom: 40px; } /* 각 제품 아이템 스타일 */ .product-item { width: 280px; /* 각 제품 아이템의 고정 너비 */ background-color: white; border: 1px solid #ddd; border-radius: 8px; padding: 20px; text-align: center; box-shadow: 0 2px 10px rgba(0,0,0,0.08); transition: transform 0.2s ease-in-out; /* 호버 애니메이션 */ } .product-item:hover { transform: translateY(-5px); /* 호버 시 살짝 위로 이동 */ } .product-item img { max-width: 100%; height: auto; border-radius: 5px; margin-bottom: 15px; /* 이미지 아래 마진 */ } .product-item h3 { font-size: 1.5em; color: #2c3e50; margin-bottom: 10px; /* 제목 아래 마진 */ } .product-item p { font-size: 0.95em; color: #666; margin-bottom: 15px; /* 문단 아래 마진 */ } /* 가격 (인라인 요소) */ .price { display: block; /* 인라인 요소였던 span을 블록 요소처럼 동작하게 함 */ font-size: 1.3em; font-weight: bold; color: #e67e22; /* 주황색 */ margin-bottom: 20px; /* 가격 아래 마진 */ } /* 구매 버튼 (인라인 요소인 a 태그를 블록처럼 꾸밈) */ .buy-button { display: inline-block; /* 버튼이면서 가로 나열 가능 */ background-color: #3498db; /* 파란색 */ color: white; padding: 10px 25px; border-radius: 5px; text-decoration: none; /* 밑줄 제거 */ font-weight: bold; transition: background-color 0.3s ease; } .buy-button:hover { background-color: #2980b9; /* 호버 시 색상 변경 */ } /* 정보 섹션 */ .info-section { text-align: center; padding: 20px; background-color: #ecf0f1; /* 연한 회색 배경 */ border-radius: 8px; margin-top: 40px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); } .info-section p { margin-bottom: 10px; } .info-section a { color: #3498db; text-decoration: none; font-weight: bold; } .info-section a:hover { text-decoration: underline; } /* 인라인 요소들의 배치 (display: inline-block 활용) */ .contact-info, .notice-info { display: inline-block; /* 옆으로 나열되면서 패딩, 마진 적용 가능 */ background-color: #fff; padding: 8px 15px; border: 1px solid #c9d9e4; border-radius: 20px; font-size: 0.9em; margin: 5px 10px; /* 요소들 간의 간격 */ } /* 푸터 스타일 */ footer { background-color: #2c3e50; color: #ecf0f1; text-align: center; padding: 20px 0; margin-top: 30px; /* 푸터 위 여백 */ font-size: 0.9em; }
-
결과 확인
- Live Server를 통해
products.html
파일을 열어보세요. - 각 제품 아이템이 사각형 박스 형태로 정돈되어 배치되고, 그 안의 콘텐츠, 패딩, 테두리, 마진이 어떻게 적용되었는지 확인해 보세요.
display: inline-block
으로 변경된 가격(span.price
)과 구매하기 버튼(a.buy-button
)의 동작을 관찰해 보세요. 이들이 어떻게 블록처럼 크기를 가지면서도 인라인처럼 옆으로 나열되는지 확인하는 것이 중요합니다..contact-info
와.notice-info
span
태그들이 옆으로 나란히 배치되는 것을 통해display: inline-block
의 효과를 다시 한번 이해할 수 있습니다.
- Live Server를 통해
이번 장에서는 CSS 레이아웃의 가장 근본적인 개념인 박스 모델(Box Model) 을 학습했습니다. 모든 HTML 요소가 콘텐츠, 패딩, 테두리, 마진으로 구성된 사각형 박스로 표현된다는 것을 이해하고, width
, height
, padding
, border
, margin
속성들을 사용하여 이 박스들의 크기와 공간을 제어하는 방법을 배웠습니다. 특히 box-sizing: border-box;
의 중요성을 강조했습니다.
또한, 요소들이 화면에 어떻게 배치되는지를 결정하는 display
속성에 대해 알아보면서, 블록(block), 인라인(inline), 그리고 둘의 장점을 결합한 인라인-블록(inline-block) 요소의 특징과 활용법을 익혔습니다. 마진 상쇄 현상과 그 해결법에 대한 심화 내용도 다루어, 더 깊은 이해를 돕고자 했습니다.