빌드노트
height: 100%인데 자식이 부모의 min-height를 채우지 않는다
부모의 min-height가 180px이어도 height: 100%인 자식은 24px에 머물 수 있다. 일반 블록의 auto·최소 높이·명시 높이를 실제 브라우저에서 비교하고, 스타일 조회값과 확정 높이의 차이 및 flex stretch를 선택할 조건을 설명한다.
부모에 min-height: 180px를 줬는데 height: 100%인 자식은 글자 한 줄 높이로 남을 수 있다. 부모와 자식이 일반 블록이고 부모의 height가 auto라면, 먼저 백분율의 기준 높이를 확인해야 한다. 최소 높이를 확보하는 것과 자식의 백분율 계산에 쓸 높이를 확정하는 것은 다르다.
이 글에서는 같은 자식을 두고 부모의 높이 선언만 바꿔 비교한다. 실제 장애 사례가 아니라 Windows의 Chromium 153.0.8010.36에서 별도로 실행한 작은 실험이다.
부모의 height가 픽셀로 나와도 선언을 다시 본다
개발자 도구의 Styles에서 부모에게 적용된 height와 min-height를 확인한다. 여기서는 직접 부모가 자식의 높이 기준인 일반 블록을 다룬다. 부모나 자식이 flex/grid item이거나 자식이 절대 위치 요소라면 아래 비교를 그대로 적용하지 않는다.
브라우저 콘솔에서는 .child를 채우려는 자식의 선택자로 바꿔 다음 코드를 실행한다. 부모와 자식의 스타일 조회값, 테두리까지 포함한 실제 높이를 함께 확인하는 코드다.
const child = document.querySelector('.child');
[child.parentElement, child].map(el => ({
role: el === child ? 'child' : 'parent',
height: getComputedStyle(el).height,
minHeight: getComputedStyle(el).minHeight,
rectHeight: el.getBoundingClientRect().height
}));
아래 실험의 min-height: 180px 조건에서는 부모의 height와 minHeight가 모두 180px, rectHeight는 208이었다. 자식은 height가 24px, minHeight가 0px, rectHeight가 24였다. 부모에게 높이가 있는데도 자식이 채우지 않는 모습이다.
이때 부모의 height 조회값이 180px라는 이유로 백분율 기준도 확정됐다고 판단하면 안 된다. getComputedStyle() 문서 (새 탭에서 열림)는 반환값을 resolved value라고 설명한다. 높이처럼 레이아웃에 의존하는 속성은 실제 배치에 사용한 값이 반환될 수 있다. 함수 이름과 달리 원래의 height: auto 선언을 그대로 보여 주는 조회가 아니다.
같은 자식으로 부모 선언만 바꿔 보았다
다음 내용을 새 HTML 파일로 저장해 브라우저에서 열면 문제 조건을 확인할 수 있다. 자식의 내용은 한 줄로 고정하고, 부모의 height와 min-height 두 선언만 바꿔 비교한다. 앞의 콘솔 코드도 이 페이지에서 실행할 수 있다.
<!doctype html>
<meta charset="utf-8">
<style>
.parent {
width: 240px;
height: auto;
min-height: 180px;
box-sizing: content-box;
padding: 12px;
border: 2px solid #222;
}
.child {
height: 100%;
min-height: 0;
box-sizing: content-box;
margin: 0;
padding: 0;
border: 0;
font: 16px/24px sans-serif;
}
</style>
<div class="parent"><div class="child">한 줄 내용</div></div>
측정한 값은 다음과 같다. 스타일 높이는 getComputedStyle(...).height, 사각형 높이는 getBoundingClientRect().height의 결과이며 단위는 CSS px다.
- 부모가
height: auto; min-height: 0이면 부모의 스타일 높이는24px, 사각형 높이는52였다. 자식은 각각24px,24였다. - 부모가
height: auto; min-height: 180px이면 부모는180px,208이 됐다. 자식은 여전히24px,24였다. - 부모가
height: 180px; min-height: 0이면 부모는180px,208이었다. 이번에는 자식도180px,180이 됐다.
두 번째와 세 번째의 부모는 화면에서 같은 높이를 차지한다. 부모의 스타일 높이 조회값까지 같다. 하지만 부모가 그 높이를 어떻게 정했는지가 달라 자식의 결과는 달라진다.
CSS에서 말하는 확정 크기(definite size)는 이 예처럼 자식의 내용 배치를 기다리지 않고 기준으로 삼을 수 있는 크기다. height: 180px가 해당하고, 확정된 높이를 기준으로 계산할 수 있는 백분율도 해당한다. 반드시 px로만 지정해야 한다는 뜻은 아니다. CSS Sizing의 크기 정의와 백분율 규칙 (새 탭에서 열림)에서 이 관계를 설명한다.
반면 일반 블록의 height: auto는 내용에 따라 높이를 정한다. 자식이 그 부모의 높이로 다시 자신의 높이를 정하려 하면 계산이 순환한다. 이 조건의 백분율 높이는 배치에서 auto처럼 동작한다. min-height: 180px는 부모의 최종 높이에 하한을 주지만, height: auto를 백분율의 확정 기준으로 바꾸지는 않는다. CSS Sizing의 내용 의존 백분율 규칙 (새 탭에서 열림)과 MDN height의 백분율 적용 조건 (새 탭에서 열림)을 함께 보면 된다.
또 하나 구별할 값은 부모의 208이다. getBoundingClientRect() (새 탭에서 열림)는 패딩과 테두리를 포함한다. 이 실험에서는 부모의 내용 높이 180에 위아래 패딩 24와 테두리 4가 더해졌다. 명시 높이 조건에서 자식의 100%가 참조한 것은 부모 내용 영역의 180px다. 자식의 패딩과 테두리는 0으로 유지했으므로 자식의 두 조회값도 일치했다.
최소 높이는 유지하면서 자식을 늘리고 싶다면
부모의 내용 높이를 정해진 값으로 유지하려는 목적이면 min-height 대신 명시적인 height를 주는 선택이 맞는다. 이 실험에서는 height: 180px로 바꾸자 기존 height: 100%인 자식이 그 내용 높이를 채웠다.
부모가 내용에 따라 자라도록 두면서 자식을 세로로 늘리려는 목적이라면, 백분율 대신 배치 방식의 채움을 사용할 수 있다. 위 HTML의 CSS 뒤에 다음 규칙을 추가해 별도로 실행했다. 부모를 행 방향 flex로 바꾸고 자식의 height: 100%를 auto로 바꾸는 수정이다.
.parent {
height: auto;
min-height: 180px;
display: flex;
flex-direction: row;
align-items: stretch;
}
.child {
height: auto;
}
같은 패딩과 테두리에서 부모의 사각형 높이는 208, 자식은 180이었다. 부모와 자식의 스타일 높이 조회값도 각각 180px였다. 여기서는 백분율을 계산해 채운 것이 아니라 flex의 stretch로 늘어난 것이다.
행 방향 flex의 교차축은 세로다. Flexbox의 stretch 규칙 (새 탭에서 열림)은 교차축 크기가 auto이고 그 축의 margin이 auto가 아닌 아이템을 늘린다. 따라서 위 수정에는 자식의 height: auto도 포함돼 있다. display: flex 한 줄만 추가하는 수정으로 읽지 않아야 한다.
이 flex 비교는 자식 하나가 있는 줄바꿈 없는 행에서 높이 채움만 확인했다. 열 방향 flex의 남은 공간 분배나 grid 배치는 실행하지 않았다. 기본 세 조건도 일반 블록, 가로 쓰기 방향, 한 줄 텍스트로 한정했으며 Firefox·Safari, 절대 위치 요소와 이미지의 백분율 높이는 검증하지 않았다. 자기 코드의 결과가 다르면 부모의 높이 선언과 배치 방식부터 이 조건과 대조한다.