본문 바로가기
빌드노트 검색

빌드노트

width 100%인데 padding을 넣자 부모 밖으로 넘친다

width 100%인 일반 블록에 padding과 border를 더하면 content-box에서는 테두리 폭이 부모보다 커진다. 320px 부모의 실측값으로 border-box 적용 전후를 비교하고, margin은 지정 폭에 포함되지 않는다는 경계까지 확인한다.

블록에 width: 100%를 줬는데 padding과 border를 더하자 부모 밖으로 넘치고 가로 스크롤이 생길 수 있다. 그 요소의 box-sizing이 content-box라면 지정한 폭은 내용 영역의 폭이다. padding과 border는 그 바깥에 붙는다. 테두리까지 부모 폭에 맞추려면 폭을 지정한 자식 요소에 box-sizing: border-box를 적용한다. MDN의 box-sizing 설명 (새 탭에서 열림)에서 두 값의 계산 범위를 확인할 수 있다.

같은 100%가 356px와 320px로 갈렸다

다른 CSS가 없는 새 문서에서 부모 폭을 320px로 고정했다. 자식은 width: 100%, 좌우 padding은 각각 16px, border는 각각 2px다. 짧은 텍스트만 넣어 긴 내용 때문에 넘치는 경우를 제외했다. 다음 내용을 새 box.html 파일에 저장하고 브라우저로 열면 같은 조건을 만들 수 있다.

<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
  .parent { width: 320px; padding: 0; border: 0; overflow: auto; direction: ltr; }
  .child { width: 100%; padding: 16px; border: 2px solid #444; margin: 0; }
</style>
<div class="parent"><div class="child">short</div></div>

이 문서의 overflow: auto는 넘친 폭을 부모 안에서 스크롤로 확인하기 위한 조건이다. 실제 페이지의 overflow 설정을 바꾸는 수정안은 아니다.

개발자 도구의 Console에서 아래 코드를 실행한다. boxSizing과 width는 적용된 스타일 값이고, rectWidth는 테두리까지의 실제 폭이다. parentClient와 parentScroll은 부모가 보여 줄 수 있는 폭과 스크롤 영역의 폭을 비교한다.

(() => {
  const box = document.querySelector('.child');
  const parent = box.parentElement;
  const css = getComputedStyle(box);
  return {
    boxSizing: css.boxSizing, width: css.width,
    rectWidth: box.getBoundingClientRect().width,
    childScroll: box.scrollWidth,
    parentClient: parent.clientWidth,
    parentScroll: parent.scrollWidth
  };
})()

Windows의 Chrome 155.0.8059.80에서 실행한 결과는 boxSizing: "content-box", width: "320px", rectWidth: 356, childScroll: 352, parentClient: 320, parentScroll: 356이었다. 별도 합성 문서에서도 화면 폭 1280px와 390px에서 같은 값을 얻었다.

내용 폭 320px에 좌우 padding 32px와 좌우 border 4px를 더하면 테두리까지 356px다. 부모보다 커진 36px가 이 조건에서 넘친 폭과 일치했다. getComputedStyle()의 width만 보면 320px이므로 문제를 놓칠 수 있다. getComputedStyle()은 적용 후 해석된 값을 반환 (새 탭에서 열림)하고, getBoundingClientRect()의 폭은 padding과 border를 포함 (새 탭에서 열림)한다.

여기서 childScroll이 352라고 해서 자식이 부모 안에 들어간 것은 아니다. 요소 자신의 scrollWidth는 자신의 border를 제외한다. 자식 전체가 부모 밖으로 나갔는지 보려면 자식의 테두리 폭과 부모의 폭을 함께 비교해야 한다. scrollWidth의 측정 범위 (새 탭에서 열림)에 설명된 차이다.

폭을 준 자식에 border-box를 적용한다

같은 파일의 CSS 맨 아래에 이 규칙을 추가하고 저장한 뒤 새로고침한다. Console의 측정 코드도 다시 실행한다.

.child { box-sizing: border-box; }

이번에는 boxSizing: "border-box", width: "320px", rectWidth: 320, childScroll: 316, parentClient: 320, parentScroll: 320이었다. padding과 border는 그대로인데 테두리까지 부모 폭 안에 들어왔다. 지정 폭 320px에서 padding 32px와 border 4px를 뺀 내용 폭은 284px가 된다. 이 284px는 측정값에서 계산한 내용 영역의 폭이며, getComputedStyle().width가 반환한 값은 여전히 320px다.

box-sizing은 상속되지 않으므로 부모에만 선언해서는 이 자식의 계산 방식이 바뀌지 않는다. 실제 코드에서도 폭과 padding을 가진 요소를 선택하고 Computed의 box-sizing을 먼저 확인한다. 이미 border-box라면 같은 선언을 더 넣어도 원인을 해결하지 못한다. CSS Box Sizing Level 3의 box-sizing 절 (새 탭에서 열림)은 이 적용 범위와 상속 여부를 정의한다. 링크는 2026년 9월 4일 Working Draft다.

margin까지 100% 안에 들어가지는 않는다

위 border-box 규칙을 유지한 채 .child에 margin-left: 16px도 추가했다. 다시 측정하면 width는 "320px", rectWidth는 320 그대로인데 parentScroll은 336으로 늘어났다. 자식의 왼쪽 테두리가 부모의 왼쪽에서 16px 밀리고, 오른쪽 테두리가 336px 지점에 놓였기 때문이다.

border-box가 포함하는 범위는 내용·padding·border까지다. margin은 그 바깥에 남는다. 부모 폭을 전부 쓰는 자식에 왼쪽 바깥 여백까지 필요하다면 그 여백만큼 차지할 공간도 따로 고려해야 한다. 이 예제에서 margin을 0으로 돌리면 부모의 스크롤 폭도 다시 320px가 됐다.

자기 화면에서 결과가 다르면 먼저 Console이 해당 문서에서 실행됐는지, .child에 다른 width·padding·border·margin 규칙이 적용됐는지 확인한다. 테두리 폭은 부모에 맞는데 스크롤 영역만 넓다면 긴 텍스트나 내부 자식이 넘치는지도 살펴본다. 이 실험은 일반 블록의 폭 계산을 확인한 것이며 flex의 자동 최소 폭이나 sticky의 기준을 검증한 것은 아니다.

직접 확인한 범위는 새 문서의 고정폭 부모, 짧은 내용, 일반 div, Chrome 한 종류다. 390px는 좁은 브라우저 화면이며 실제 모바일 기기 검증은 하지 않았다. 또한 문서상 padding과 border의 합계 자체가 지정 폭보다 크면 내용 폭은 0까지만 줄어든다. border-box가 어떤 조건에서도 넘침을 없애 준다고 해석해서는 안 된다.

← 목록으로 돌아가기