CSS box-sizing content-box와 border-box 차이
CSS에서 width를 지정했는데 요소가 예상보다 넓어질 때가 있다.
대부분 padding과 border가 최종 너비에 더해졌기 때문이다.
box-sizing은 width와 height가 박스의 어느 영역까지 포함하는지 정한다.
기본값인 content-box는 content 크기만 지정한다.border-box는 content, padding, border를 합친 크기를 지정한다.
레이아웃 너비를 예측하기 쉽게 만들고 싶다면 두 계산 방식의 차이부터 이해해야 한다.
CSS 박스 모델의 구성
HTML 요소는 안쪽부터 content, padding, border, margin 영역으로 구성된다.
.box {
width: 300px;
padding: 20px;
border: 2px solid #333;
margin: 24px;
}content는 글자나 이미지가 놓이는 영역이다.
padding은 content와 border 사이의 안쪽 여백이다.
border는 요소의 테두리다.
margin은 border 바깥에서 다른 요소와 거리를 만든다.
box-sizing은 이 가운데 content, padding, border와 width의 관계를 바꾼다.
margin은 어떤 값을 사용해도 지정한 width에 포함되지 않는다.
안쪽 여백과 바깥 간격의 차이는 CSS margin과 padding 차이에서 더 자세히 다뤘다.
content-box의 계산 방식
content-box는 CSS 표준에서 정한 box-sizing의 초기값이다.
지정한 width와 height가 content 영역에만 적용된다.
.box {
box-sizing: content-box;
width: 300px;
padding: 20px;
border: 2px solid #333;
}이 요소의 content 너비는 300px이다.
좌우 padding은 각각 20px이므로 합계가 40px이다.
좌우 border는 각각 2px이므로 합계가 4px이다.
브라우저에 그려지는 border 바깥쪽 너비는 다음과 같다.
300px + 20px + 20px + 2px + 2px = 344pxCSS에 width: 300px을 적었지만 눈에 보이는 박스는 344px을 차지한다.
content 영역을 정확히 300px로 유지해야 한다면 이 동작이 필요할 수 있다.
border-box의 계산 방식
border-box는 지정한 width 안에 content, padding, border를 모두 포함한다.
.box {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid #333;
}브라우저에 그려지는 border 바깥쪽 너비는 그대로 300px이다.
padding과 border가 그 안에 들어가므로 content 영역이 줄어든다.
content 너비는 다음과 같다.
300px - 20px - 20px - 2px - 2px = 256px박스의 최종 너비를 300px로 유지하는 대신 실제 content가 사용할 수 있는 너비는 256px이 된다.
레이아웃에서는 최종 크기를 바로 읽을 수 있어 border-box가 편한 경우가 많다.
두 값의 핵심 차이
두 값은 width가 의미하는 범위에서 차이가 난다.
content-box에서width는 content 영역의 너비다.border-box에서width는 content, padding, border를 합친 너비다.content-box는 padding과 border가 최종 박스 크기에 더해진다.border-box는 padding과 border가 지정한 크기 안으로 들어간다.- margin은 두 방식 모두
width바깥에서 계산된다. box-sizing의 초기값은content-box다.
content 자체의 정확한 크기가 중요하면 content-box를 고려할 수 있다.
화면에 배치되는 최종 박스 크기가 중요하면 border-box가 읽기 쉽다.
width 100%와 overflow
초보자가 자주 만나는 문제는 width: 100%인 요소가 부모를 넘는 상황이다.
.parent {
width: 320px;
}
.child {
width: 100%;
padding: 20px;
border: 1px solid;
}기본 content-box에서는 child의 content 너비가 부모의 320px을 사용한다.
여기에 좌우 padding 40px과 border 2px이 더해진다.
최종 너비는 362px이 되어 부모보다 커진다.
border-box를 적용하면 padding과 border가 100% 안에 포함된다.
.child {
box-sizing: border-box;
width: 100%;
padding: 20px;
border: 1px solid;
}이제 최종 너비가 부모의 content 너비 안에 맞는다.
다만 overflow의 원인이 항상 box-sizing인 것은 아니다.
긴 단어, 고정 너비 자식, transform, 음수 margin, grid track의 최소 크기도 함께 확인해야 한다.
전역 border-box 설정
많은 프로젝트는 모든 요소에 border-box를 기본으로 적용한다.
*,
*::before,
*::after {
box-sizing: border-box;
}모든 일반 요소와 pseudo-element가 같은 계산 방식을 사용한다.
컴포넌트마다 box-sizing을 반복해서 적지 않아도 된다.
상속을 활용하는 방식도 있다.
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}특정 subtree에서 계산 방식을 바꾸고 싶을 때 상속 구조가 편할 수 있다.
프로젝트의 reset이나 normalize 파일에 이미 설정되어 있을 가능성이 높다.
새 규칙을 추가하기 전에 현재 전역 스타일을 먼저 확인하는 편이 좋다.
height 계산의 차이
box-sizing은 너비뿐 아니라 높이에도 같은 방식으로 적용된다.
.box {
box-sizing: content-box;
height: 100px;
padding-block: 16px;
border-block: 2px solid;
}content-box의 최종 높이는 100px + 32px + 4px인 136px이다.
.box {
box-sizing: border-box;
height: 100px;
padding-block: 16px;
border-block: 2px solid;
}border-box의 최종 높이는 100px이다.
content가 사용할 수 있는 높이는 64px로 줄어든다.
고정 높이에 padding을 많이 넣으면 content 영역이 너무 작아질 수 있다.
텍스트가 여러 줄이 되는 UI에서는 height보다 min-height가 안전한 경우가 많다.
padding이 content를 줄이는 동작
border-box는 padding을 무시하지 않는다.
padding을 지정한 최종 크기 안에 넣기 위해 content 영역을 줄인다.
.button {
box-sizing: border-box;
width: 120px;
padding-inline: 24px;
}좌우 padding이 합계 48px이므로 텍스트가 사용할 수 있는 공간은 그만큼 작아진다.
버튼 label이 길면 줄바꿈되거나 넘칠 수 있다.
border-box를 사용하면 모든 크기 문제가 자동으로 해결된다고 생각하면 안 된다.
지정한 너비 안에서 content와 padding이 나눠 쓴다는 점을 함께 봐야 한다.
margin이 포함되지 않는 이유
border-box라는 이름처럼 계산 범위는 border edge까지다.
margin은 요소 바깥의 다른 박스와 간격을 만들기 때문에 width에 포함되지 않는다.
.box {
box-sizing: border-box;
width: 300px;
margin-inline: 20px;
}박스 자체의 너비는 300px이다.
레이아웃에서 차지하는 가로 범위는 좌우 margin까지 고려하면 340px이 될 수 있다.
부모 안에서 여러 열을 계산할 때 margin 때문에 넘친다면 gap을 사용하는 구조도 검토할 수 있다.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}항목 사이 간격을 부모가 관리하면 각 item의 바깥 너비 계산이 단순해진다.
input과 button의 기본값
모든 요소가 브라우저 기본 스타일에서 같은 box-sizing을 쓰는 것은 아니다.
MDN에 따르면 일부 form control과 table 요소는 기본적으로 border-box를 사용한다.
그래서 같은 width를 준 div와 button의 크기가 다르게 보일 수 있다.
.box,
.button {
width: 200px;
padding: 16px;
border: 2px solid;
}전역 border-box 설정은 이런 기본값 차이를 줄이고 크기 계산을 통일하는 데도 도움이 된다.
HTML에서 링크와 버튼을 선택하는 의미 기준은 HTML button과 a 태그 차이에서 확인할 수 있다.
min-width와 max-width
box-sizing은 min-width와 max-width가 해석되는 범위에도 영향을 준다.
.panel {
box-sizing: border-box;
width: 100%;
max-width: 720px;
padding-inline: 24px;
}border-box에서는 panel의 content, padding, border를 합친 너비가 720px을 넘지 않는다.
반대로 content-box에서는 max-width가 content 영역에 적용되고 padding과 border가 바깥에 더해진다.
페이지 container처럼 최종 외곽 너비를 제한하려면 border-box가 이해하기 쉽다.
DevTools에서 확인하는 방법
브라우저 DevTools의 Computed panel에는 box model 그림이 표시된다.
content, padding, border, margin의 실제 계산 값을 한눈에 볼 수 있다.
요소가 예상보다 크다면 다음 순서로 확인한다.
- Computed style에서
box-sizing값을 확인한다. width와height의 computed value를 확인한다.- 좌우 또는 위아래 padding 합계를 확인한다.
- border 두께를 확인한다.
- margin과 부모의
gap을 별도로 확인한다. - 자식 콘텐츠가 overflow를 만드는지 확인한다.
스타일 선언만 읽는 것보다 브라우저가 계산한 box model을 보면 원인을 빠르게 찾을 수 있다.
content-box를 사용하는 경우
border-box가 항상 정답은 아니다.
content 영역의 크기 자체를 고정해야 한다면 content-box가 의도를 더 정확하게 표현할 수 있다.
.canvas-preview {
box-sizing: content-box;
width: 640px;
height: 360px;
padding: 12px;
border: 1px solid;
}실제 미디어나 좌표계가 들어가는 content 영역을 정확히 640 × 360으로 유지하고, frame을 바깥에 더하려는 경우다.
하지만 일반적인 카드, input, button, page container처럼 외곽 크기를 기준으로 배치하는 UI에서는 border-box가 더 직관적인 경우가 많다.
자주 생기는 실수
width: 100%에 padding을 추가한 뒤 가로 스크롤이 생겼다면 box-sizing을 확인한다.
border-box를 적용했는데 글자가 잘린다면 padding과 border가 content 공간을 얼마나 줄였는지 계산한다.
고정 height에 padding을 넣고 내용이 넘친다면 min-height로 바꿀 수 있는지 살펴본다.
전역 reset이 있는데 컴포넌트에서 content-box로 덮어쓴 곳이 없는지 확인한다.
margin까지 width에 포함된다고 생각하지 않는다.
pseudo-element만 크기가 다르게 보인다면 *::before, *::after에도 설정이 적용되는지 확인한다.
선택 기준
레이아웃에 배치되는 최종 박스 너비와 높이를 CSS 값 그대로 읽고 싶다면 border-box를 사용한다.
.card {
box-sizing: border-box;
width: 320px;
padding: 24px;
}content 영역 자체를 지정한 크기로 유지하고 padding과 border를 바깥에 더하려면 content-box를 사용한다.
.preview {
box-sizing: content-box;
width: 640px;
}대부분의 UI 프로젝트에서는 전역 border-box를 기본으로 두고, 정말 필요한 요소만 content-box로 바꾸는 흐름이 이해하기 쉽다.
정리
content-box에서 width는 content 영역만 뜻한다.
padding과 border는 최종 박스 크기에 추가된다.
border-box에서 width는 content, padding, border를 합친 크기다.
padding과 border가 늘어나면 그만큼 content 영역이 줄어든다.
margin은 두 방식 모두 지정한 width에 포함되지 않는다.
요소가 예상보다 커졌다면 먼저 현재 box-sizing과 좌우 padding, border를 확인하면 된다.
최종 외곽 크기를 기준으로 레이아웃을 만들 때는 border-box가 계산을 단순하게 만든다.
참고 자료




