01 — Box Model

모든 HTML 요소는 4겹의 동심 사각형이다 — content → padding → border → margin. 이 4겹의 합이 어디까지를 “요소의 크기”로 칠 것인지가 박스 모델이고, 2012년 이후 border-box가 사실상 표준이 되었다.


Why — 왜 박스 모델이 모든 것의 출발인가

CSS 렌더링 엔진은 트리의 모든 노드를 사각형으로 환원해서 레이아웃을 계산한다. text run 하나, 인라인 SVG 하나, <div> 하나 — 전부 박스다. 박스의 크기 계산이 어긋나면:

  • width: 100%인데 가로 스크롤이 생긴다.
  • flex: 1인 자식들이 의도와 다른 비율로 늘어난다.
  • 그리드 셀이 gap을 무시하고 겹친다.
  • position: absolute 요소의 inset이 어긋난다.

박스 모델은 CSS의 산수다. 모든 계산이 여기서 시작한다.


How — 박스는 어떻게 구성되나

브라우저는 모든 요소에 대해 4개의 사각형을 계산한다. 안쪽부터:

┌─────────────────────────────── margin box ──────┐
│        margin (배경 없음, 투명)                  │
│  ┌────────────────────────── border box ──┐    │
│  │   border (색·스타일 가짐)                │    │
│  │  ┌─────────────────── padding box ──┐  │    │
│  │  │  padding (배경색이 칠해지는 영역)  │  │    │
│  │  │  ┌─────────── content box ──┐    │  │    │
│  │  │  │   content                 │    │  │    │
│  │  │  └───────────────────────────┘    │  │    │
│  │  └────────────────────────────────────┘  │    │
│  └──────────────────────────────────────────┘    │
└──────────────────────────────────────────────────┘

box-sizing 속성이 widthheight는 이 중 어느 박스를 가리키는가” 를 결정한다.

box-sizingwidth/height가 의미하는 것비고
content-box (기본값)content box만W3C CSS1 초안 모델
border-boxpadding + border 포함 (margin 제외)IE5가 먼저 채택, 2012년 이후 사실상 표준

계산 예시

.box {
  width: 200px;
  padding: 20px;
  border: 5px solid;
  margin: 10px;
}
box-sizing실제 요소 너비margin 포함비고
content-box200 + 20·2 + 5·2 = 250px270pxwidth에 padding/border가 더해진다
border-box200px220pxcontent는 200 - 50 = 150px줄어든다

What — 구체 사양과 패턴

1) 모든 리셋의 첫 줄

*, *::before, *::after {
  box-sizing: border-box;
}

이 한 줄은 normalize.css, modern CSS reset, Tailwind preflight, shadcn/ui, Bootstrap 5 — 모든 모던 리셋에 들어 있다.

2) margin collapsing (마진 상쇄)

블록 박스의 수직 인접 margin은 합쳐진다 (flex/grid 자식은 예외).

h2 { margin-bottom: 24px; }
p  { margin-top: 16px; }
/* h2와 p 사이 간격은 40px이 아니라 max(24, 16) = 24px */

상쇄 발생 조건:

  • 인접한 형제 (sibling)
  • 부모와 첫 자식 / 마지막 자식 (부모에 padding이나 border 없을 때)
  • 빈 블록의 위·아래 margin

상쇄를 막는 법:

  • 부모를 BFC로 만든다 (display: flow-root / flex / grid / overflow: hidden)
  • padding이나 border를 1px이라도 준다
  • flex/grid 컨테이너 안에서는 애초에 발생하지 않는다

3) min-content / max-content / fit-content

width/height에 키워드 값을 줄 수 있다 — intrinsic sizing.

.button { width: max-content; padding: 8px 16px; }
/* 텍스트가 줄바꿈 없이 가장 좁은 너비로 */
키워드의미
min-content줄바꿈 가능한 가장 작은 너비 (가장 긴 단어 폭)
max-content줄바꿈 없는 가장 큰 너비
fit-content(N)min과 max 사이에서 N으로 clamp
auto부모와 흐름에 맡김 (기본값)

4) aspect-ratio (2021년 이후 Baseline)

박스 모델 위에 종횡비를 강제하는 모던 속성.

.video-wrapper { aspect-ratio: 16 / 9; width: 100%; }
.avatar       { aspect-ratio: 1;     width: 48px;  }

width만 정하면 height가 자동 계산된다. 과거의 padding-bottom: 56.25% hack을 폐기시킨다.


What-if — 잘못 쓰면

1) box-sizing 없이 width: 100% + padding

.col { width: 100%; padding: 0 16px; }
/* content-box 기본값이면 → 실제 너비 = 100% + 32px → 가로 스크롤 발생 */

이게 *“왜 가로 스크롤이 생기지”*의 90%다.

2) 마진 상쇄를 모르는 채로 레이아웃 짜기

.section { margin-top: 80px; }
.section:first-child { margin-top: 0; }
/* 부모의 padding-top이 0이면, 부모 위로 80px이 "삐져나간다" — margin이 부모를 뚫고 합쳐진다 */

해결: 부모를 BFC로 (display: flow-root).

3) width: auto인 inline 요소에 width를 주려는 시도

<span>width: 200px을 줘도 무시된다. inline 박스는 content가 결정한다. display: inline-block 또는 block이 필요.

4) flex/grid 자식의 min-width: auto

flex/grid 자식의 기본 min-widthauto이고, 이는 content의 min-content다. 긴 텍스트가 있으면 자식이 부모를 넘어선다.

.flex-child { min-width: 0; } /* 또는 overflow: hidden */

이게 “flex 자식이 부모를 뚫고 나가는” 현상의 정답이다.


Insight — Paul Irish의 한 줄 트윗이 사실상 표준을 바꿨다

2012년 2월 1일 — Paul Irish는 자신의 블로그에 다음 한 줄을 올렸다:

*, *:before, *:after { box-sizing: border-box; }

제목은 “box-sizing: border-box FTW”. 그는 이 한 줄이 “CSS 작업의 30%를 줄여준다” 고 썼다.

이전까지 웹 개발자들은 두 박스 모델 사이에서 끊임없이 계산기를 두드렸다. width: 100%padding: 20px을 주려면 calc(100% - 40px)을 쓰거나, padding을 내부 자식으로 옮기거나, width를 줄여서 보정해야 했다.

흥미로운 점은 IE5(1999)가 처음부터 border-box였다는 것. 당시 W3C는 IE5를 “버그”라 불렀고, IE6에서 quirks mode를 도입해 standards mode와 분리시켰다. 그러나 시간이 지나 보니, IE5의 디자이너가 옳았다 — 사람이 “박스의 크기”라고 부르는 것은 보통 border까지를 포함하는 시각적 경계다.

CSS3 명세에 box-sizing 속성이 들어간 것이 2003년, 모든 브라우저가 지원한 것이 2012년 즈음. 그리고 그 해 Paul Irish의 트윗이 “이걸 모든 프로젝트의 첫 줄로 쓰자” 는 합의를 만들어냈다. 표준이 늦게 따라오고, 사실상 표준이 먼저 자리잡는 — 이게 CSS의 진화 패턴이다.

오늘날 Bootstrap, Tailwind, shadcn/ui, Material UI는 모두 첫 줄에 *, *::before, *::after { box-sizing: border-box }를 둔다. 13년이 지난 한 줄 트윗의 유산이다.


요약 + Mermaid

  • 모든 요소는 4겹의 박스 (content → padding → border → margin).
  • box-sizing: border-box사실상 표준 (Paul Irish 2012).
  • 마진 상쇄는 블록 흐름의 특수 규칙 — flex/grid·BFC에서는 무효.
  • min-content/max-content/fit-contentintrinsic sizing.
  • aspect-ratio로 종횡비를 선언적으로 잡는다.
  • flex 자식이 부모를 뚫으면 min-width: 0.