웹 페이지를 만들다 보면 요소의 너비와 높이를 정했는데 레이아웃이 자꾸 깨진다는 경험이 흔하다. 특히 padding이나 border를 추가했을 때 요소가 예상보다 커지는 현상을 겪는 개발자들이 많다. 다만 이 문제의 정확한 원인과 해결책을 제대로 아는 사람은 드물다. 이번에는 CSS Box Model이 정확히 뭔지, 왜 계산 오류가 발생하는지, box-sizing 속성으로 어떻게 완벽히 해결하는지 실무 기반으로 정리해서 소개하겠다.
CSS Box Model은 모든 HTML 요소를 감싸는 네 개의 레이어로 이루어져 있다. 바깥쪽부터 margin, border, padding, content 순서다. 브라우저가 요소의 최종 크기를 계산할 때 이 네 개 레이어를 어떻게 포함하는지에 따라 전혀 다른 크기가 나온다.
기본적으로 HTML 요소에 width: 200px을 지정하면 content 영역만 200px이 된다. 만약 padding: 20px, border: 5px, margin: 10px을 추가하면 실제 차지하는 전체 공간은 200 + 20*2 + 5*2 + 10*2 = 270px이 된다. 대부분의 개발자들은 width 값을 정했을 때 그 너비로 끝날 거라고 생각하지만, 실제로는 padding과 border를 더하면 훨씬 커진다.
CSS에는 두 가지 박스 모델 방식이 있다. 첫 번째는 W3C 표준 박스 모델(content-box)이고, 두 번째는 IE에서 만들었던 대체 박스 모델(border-box)이다. 현대 브라우저는 기본적으로 content-box를 사용한다. 이것이 레이아웃 깨짐의 가장 큰 원인이다.
| 박스 모델 | width/height 포함 범위 | 전체 크기 계산 |
|---|---|---|
| content-box (기본값) | content만 | width + padding*2 + border*2 + margin*2 |
| border-box | content + padding + border | width + margin*2 |
box-sizing 속성으로 어떤 박스 모델을 사용할지 명시적으로 지정할 수 있다. 실무에서는 대부분 border-box를 전역에 적용해서 계산을 간단하게 만든다.
/* ✗ 잘못된 방법: 요소마다 일일이 지정 */
.box {
width: 200px;
padding: 20px;
border: 5px solid #000;
box-sizing: border-box; /* 이 요소만 border-box */
}
.sidebar {
width: 300px;
padding: 15px;
box-sizing: border-box; /* 다른 요소도 일일이 지정 */
}
/* 결과: 일관성 없고 유지보수 어려움 */
/* ✓ 올바른 방법: 전역 재설정 */
* {
margin: 0;
padding: 0;
box-sizing: border-box; /* 모든 요소에 적용 */
}
.box {
width: 200px; /* 이제 padding과 border를 포함해서 정확히 200px */
padding: 20px;
border: 5px solid #000;
}
.sidebar {
width: 300px; /* padding과 border 포함해서 정확히 300px */
padding: 15px;
}
/* 결과: 전체 레이아웃이 일관되고 계산이 간단 */
이 방식의 장점은 width와 height 값이 정확하게 그대로 요소의 최종 크기가 된다는 것이다. padding이나 border를 추가해도 너비가 늘어나지 않는다.
실제 프로젝트에서 자주 겪는 상황이 그리드 레이아웃이다. 두 개의 칸을 각각 50%씩 배치하고 싶지만, padding 때문에 겹치는 문제가 흔하다.
<!-- HTML 구조 -->
<div class="container">
<div class="column">Column 1</div>
<div class="column">Column 2</div>
</div>
/* ✗ box-sizing 없을 때: 두 칸이 한 줄에 안 맞음 */
.column {
width: 50%; /* content 영역만 50% */
padding: 20px; /* 양쪽에 20px씩 추가됨 */
border: 1px solid #ddd;
float: left;
box-sizing: content-box; /* 명시적으로 기본값 설정 */
}
/* 결과: 50% + 40px(padding) + 2px(border) = 50% + 42px
두 칸 합계: 100% + 84px → 화면을 넘어감 */
/* ✓ box-sizing: border-box 적용 */
* {
box-sizing: border-box;
}
.column {
width: 50%; /* padding과 border를 포함해서 정확히 50% */
padding: 20px;
border: 1px solid #ddd;
float: left;
}
/* 결과: 두 칸 합계: 50% + 50% = 100% → 정확하게 한 줄에 맞음 */
이 차이가 실무에서 얼마나 중요한지 알 수 있다. box-sizing: border-box 한 줄로 복잡한 계산을 완전히 피할 수 있다.
✗ border-box를 일부 요소에만 적용해서 섞어 쓰기
일부 요소는 content-box, 일부는 border-box로 혼용하면 레이아웃 계산이 일관되지 않는다. 결국 width를 다시 조정하거나 하드코딩하는 악순환이 반복된다. 프로젝트 전역에 통일해야 한다.
✓ 프로젝트 시작 시 CSS Reset에 포함시키기
/* CSS 파일 맨 처음에 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
/* 이후 모든 요소는 기본적으로 border-box 적용됨 */
✗ 외부 라이브러리와 충돌
부트스트랩, 테일윈드 같은 CSS 프레임워크는 이미 전역에서 box-sizing: border-box를 적용하고 있다. 만약 직접 CSS를 작성하면서 다시 content-box로 되돌리면 충돌한다. 라이브러리와 맞춰서 통일하자.
✓ 개발자 도구로 실시간 확인
브라우저의 개발자 도구(F12) > Elements에서 요소를 선택하면 Box Model 시각화 창이 나온다. 여기서 실제 margin, border, padding, content 크기를 바로 확인할 수 있다. 레이아웃이 깨졌을 때 이 도구로 width 값이 어떻게 계산되는지 디버깅하는 게 가장 빠르다.
CSS Box Model 계산 오류는 기본 개념만 이해해도 완벽히 피할 수 있다. 기본값 content-box에서 padding과 border는 width에 덧붙여지고, border-box로 변경하면 width 안에 포함된다. box-sizing은 프로젝트 시작 시 전역에 적용하는 게 표준이다. 이 작은 설정 하나가 레이아웃 오류를 90% 이상 줄여준다. 혹시 지금까지 요소마다 일일이 padding과 width를 맞춰가며 개발했다면, 이 글의 전역 CSS Reset 코드를 복사해서 다음 프로젝트부터 바로 적용해보자. 계산이 훨씬 간단하고 유지보수도 쉬워질 것이다.