모바일에서 height: 100vh를 줬더니 화면 아래가 잘린 이유
문제 발생
전체 화면 히어로 섹션에 height: 100vh를 줬더니 데스크톱에서는 정확한데 모바일에서 아래쪽 버튼이 주소창에 가려졌습니다. 스크롤하면 보였다가, 위로 올리면 다시 가려졌습니다.
.hero { height: 100vh; }원인 분석
모바일 브라우저에는 뷰포트 높이가 하나가 아닙니다. 주소창과 하단 바가 스크롤에 따라 나타났다 사라지므로, "화면 높이"가 상황에 따라 다릅니다.
CSS는 이를 세 가지로 나눕니다.
| 단위 | 기준 | 결과 |
|---|---|---|
lvh (large) | 브라우저 UI가 숨겨진 상태의 높이 | UI가 나타나면 그만큼 잘림 |
svh (small) | 브라우저 UI가 모두 보이는 상태의 높이 | 항상 들어가지만 UI가 숨으면 여백이 남음 |
dvh (dynamic) | UI에 따라 실시간으로 변하는 높이 | 딱 맞지만 스크롤 중 값이 바뀜 |
그리고 vh는 lvh와 같습니다. 즉 기본값이 "주소창이 없다고 가정한 높이"라서, 주소창이 보이는 순간 100vh짜리 요소는 화면보다 커집니다. 위 증상이 정확히 이것입니다.
dvh가 만능은 아닙니다. MDN도 스크롤 도중 콘텐츠가 리사이즈되어 UI가 흔들리고 성능에도 부담이 될 수 있다고 명시합니다.
해결 방안
- "항상 잘리지 않아야 한다"면
svh를 씁니다. UI가 숨으면 아래에 여백이 생기지만, 콘텐츠가 가려지는 것보다는 낫습니다.
.hero { height: 100svh; }- 정확히 화면을 채워야 하는 앱 셸이라면
dvh를 씁니다. 스크롤이 없는 고정 레이아웃이면 리사이즈 문제가 애초에 생기지 않습니다. 이 프로젝트의 글쓰기 화면이 그 경우로, 한 화면에 딱 맞춰야 해서calc(100dvh - 헤더 높이)를 씁니다. - 헤더 높이를 뺄 때는 실제 점유 높이를 뺍니다. 보더가 있으면 그것까지 포함해야 1px 스크롤이 생기지 않습니다.
.app-shell { height: calc(100dvh - var(--header-height)); }- min-height와 height를 구분합니다.
min-height는 바닥선이라 콘텐츠가 길면 그만큼 늘어납니다. "한 화면에 가둔다"가 목적이면height여야 합니다. - 가로 축에도 같은 단위가 있습니다.
svw/lvw/dvw, 그리고 논리 축 버전인svi/svb등도 같은 규칙을 따릅니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.