박스 모델과 요소 배치
content·padding·border·margin의 크기 계산과 box-sizing을 이해하고 display별 배치 차이를 익힙니다.
지난 장에서 우리는 CSS를 이용해 웹 페이지의 색상, 폰트, 텍스트 스타일을 섬세하게 조절하는 방법을 배웠습니다.
이제 HTML 요소들이 화면에 어떻게 배치되고 공간을 차지하는지에 대한 근본 원리인 CSS 박스 모델(Box Model)을 이해할 차례입니다.
화면에 표시되는 일반적인 HTML 요소의 크기와 여백은 박스(Box)로 이해할 수 있습니다. display: none처럼 레이아웃 박스를 만들지 않는 경우와 여러 줄에 걸친 인라인 조각은 뒤에서 구분합니다.
이 박스들이 어떻게 상호작용하고 공간을 차지하는지 이해하는 것은 웹 레이아웃을 정확하게 제어하는 데 필수적입니다.
이 장에서는 CSS 박스 모델 구성 요소와, 각 요소의 크기/여백을 제어하는 핵심 속성을 정리합니다.
또한 HTML 요소가 화면에 배치되는 기본 방식과, 이 방식을 제어하는 display 속성도 함께 알아보겠습니다.
이 지식은 복잡한 웹 레이아웃을 구현하기 위한 단단한 기반이 될 것입니다.
BOX MODEL
box-sizing은 width에 포함할 영역을 바꿉니다
같은 width: 200px, padding: 20px, border: 5px이어도 테두리까지의 폭은 달라집니다. margin은 width에 포함되지 않습니다.
content-box · 테두리까지 250px
width 200 + 좌우 padding 20×2 + 좌우 border 5×2 = 250px. 콘텐츠 폭은 200px입니다.
border-box · 테두리까지 200px
지정 width 200px 안에 padding과 border를 포함합니다. 콘텐츠 폭은 200−40−10 = 150px입니다.
위 예시의 margin은 별도입니다. 아주 작은 지정 크기에서는 콘텐츠 폭이 0 아래로 줄지 않아 padding·border가 지정 width보다 커질 수 있습니다.
바깥 역할 · block / inline
자신이 normal flow에 참여하는 방식을 정합니다. flex는 block flex, inline-flex는 inline flex의 역할입니다.
안쪽 배치 · flow / flex / grid
자식을 어떤 레이아웃 문맥으로 배치할지 정합니다. 박스 크기 계산과는 별개의 책임입니다.
CSS 박스 모델: 모든 HTML 요소는 상자다!
이 절에서는 크기와 여백을 계산할 수 있는 일반 요소의 박스 모델을 다룹니다.
즉, 여러분이 본 모든 div, p, img, a 태그는 화면에서 보이지 않는 사각형 박스로 둘러싸여 있다고 생각할 수 있습니다.
이 박스 모델은 콘텐츠, 패딩, 테두리, 마진이라는 네 가지 주요 구성 요소로 이루어져 있습니다.
박스 모델의 구성 요소
- 텍스트, 이미지, 비디오 등 요소의 실제 내용이 들어가는 영역입니다.
- 기본
box-sizing: content-box에서는width와height가 이 영역을 기준으로 합니다.border-box는 패딩과 테두리까지 포함하므로 다음 계산에서 구분합니다.
- 콘텐츠 영역과 테두리(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 - 시계 방향)
- 패딩과 마진(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
- 테두리(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-boxwidth,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 안에 포함됨) */ }
요소의 실제 크기를 계산할 때는 box-sizing을 먼저 확인하고 콘텐츠·패딩·테두리·마진을 구분합니다. 위의 “실제 너비”는 테두리 바깥까지의 폭입니다. 다른 요소와의 가로 간격까지 보려면 여기에 좌우 마진을 별도로 더합니다. border-box도 마진을 지정 너비 안에 포함하지 않습니다.
display 속성: 요소의 기본 배치 방식
모든 HTML 요소는 기본적으로 display라는 속성을 가지고 있으며, 이 속성 값에 따라 웹 페이지에 어떻게 나타나고 공간을 차지하는지가 결정됩니다.
CSS를 사용하여 이 display 속성 값을 변경함으로써 요소의 배치 방식을 제어할 수 있습니다.
블록(Block) 요소
-
일반 흐름의 블록 배치에서는 새로운 줄에서 시작합니다. Flex·Grid 아이템이나 위치 지정된 요소는 해당 레이아웃 문맥을 따릅니다.
-
부모 요소의 가로 너비(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) 요소
-
새로운 줄에서 시작하지 않고, 콘텐츠의 흐름에 따라 이전 요소 바로 옆에 배치됩니다.
-
콘텐츠의 너비만큼만 공간을 차지합니다.
-
<span>처럼 일반 인라인 요소의width,height는 적용되지 않습니다. 콘텐츠 크기에 따라 배치되며, 이미지 같은 대체 요소나 다른display를 사용하는 컨트롤은 구분해서 봅니다. -
일반 인라인 요소에는
margin-top,margin-bottom이 적용되지 않습니다. 위아래 padding·border는 그려지지만 줄의 높이를 그만큼 늘리지 않아 겹쳐 보일 수 있습니다. 좌우 margin·padding은 적용됩니다. -
예시:
<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를 두면 분리할 수 있습니다. 이것이 형제 마진까지 항상 막는 것은 아닙니다. Flex·Grid 컨테이너의 아이템 사이에는 이 마진 상쇄 규칙이 적용되지 않습니다.
실습: 박스 모델과 display 속성 활용
지금까지 배운 박스 모델과 display 속성들을 활용하여 간단한 제품 목록 페이지를 만들어 봅시다.
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">
<h3>멋진 제품 A</h3>
<p>이 제품은 정말 멋집니다. 한 번 사용해 보세요!</p>
<span class="price">25,000원</span>
<a href="#" class="buy-button">구매하기</a>
</div>
<div class="product-item">
<h3>매력적인 제품 B</h3>
<p>당신을 더욱 빛나게 할 아이템입니다.</p>
<span class="price">40,000원</span>
<a href="#" class="buy-button">구매하기</a>
</div>
<div class="product-item">
<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">문의: [email protected]</span>
<span class="notice-info">공지사항: 배송 지연 안내</span>
</div>
</main>
<footer>
<p>© 2025 우리 가게. 모든 권리 보유.</p>
</footer>
</body>
</html>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파일을 열어 보세요. - 각 제품 아이템이 사각형 박스 형태로 정돈되어 배치되고, 그 안의 콘텐츠, 패딩, 테두리, 마진이 어떻게 적용되었는지 확인해 보세요.
- 가격(
span.price)은display: block이라 새 줄을 차지하고, 구매하기 버튼(a.buy-button)은inline-block이라 인라인 흐름에 있으면서 크기를 가집니다. 두 요소의 코드와 화면을 비교해 보세요. .contact-info와.notice-info는 공간이 충분하면 나란히 있고 좁으면 다음 줄로 갑니다.inline-block은 한 줄 고정이 아니라 인라인 흐름 안에서 자체 박스 크기를 갖는 방식입니다. 이 HTML은 제품 이미지를 넣지 않았으므로.product-item img규칙의 효과는 아직 관찰 대상이 아닙니다.
이번 장에서는 CSS 레이아웃의 가장 근본적인 개념인 박스 모델(Box Model)을 학습했습니다.
모든 HTML 요소가 콘텐츠, 패딩, 테두리, 마진으로 구성된 사각형 박스로 표현된다는 것을 이해하고, width, height, padding, border, margin 속성들을 사용하여 이 박스들의 크기와 공간을 제어하는 방법을 배웠습니다.
특히 box-sizing: border-box;의 중요성을 강조했습니다.
또한, 요소들이 화면에 어떻게 배치되는지를 결정하는 display 속성에 대해 알아보면서, 블록(block), 인라인(inline), 그리고 둘의 장점을 결합한 인라인-블록(inline-block) 요소의 특징과 활용법을 익혔습니다.
마진 상쇄 현상과 그 해결법에 대한 심화 내용도 다루어, 더 깊은 이해를 돕고자 했습니다.
박스 모델은 content, padding, border, margin 네 영역과 바깥 layout context를 함께 봐야 합니다.
직접 계산: 들어가는 박스와 넘치는 박스
내용 폭 width: 200px, 좌우 패딩 각각 20px, 좌우 테두리 각각 5px, 좌우 마진 각각 10px인 박스 하나를 가로 260px의 공간에 놓습니다. 가로 마진이 별도로 더해지는 조건에서 content-box와 border-box 각각의 테두리 폭·콘텐츠 폭·마진 포함 폭을 구하고 어느 것이 들어가는지 판단하세요.
영역별 계산 확인
content-box: 콘텐츠 200px, 테두리까지 200+40+10=250px, 마진 포함 270px이므로 260px을 넘습니다. border-box: 테두리까지 200px, 콘텐츠 200−40−10=150px, 마진 포함 220px이므로 들어갑니다. 화면을 숨기는 overflow: hidden으로 계산을 대신하지 말고 개발자 도구 Box Model에서 각 영역을 대조하세요.
실습의 .product-item은 border-box에서 280px이고 패딩 20px씩·테두리 1px씩이므로 콘텐츠 폭은 238px입니다.