본문으로 건너뛰기
개발 머꼬
개발 노트CSS
hohyeon.dev15

모바일에서 height: 100vh를 줬더니 화면 아래가 잘린 이유

  • #CSS
  • #Engineering Note
  • #Layout
  • #Mobile

문제 발생

전체 화면 히어로 섹션에 height: 100vh를 줬더니 데스크톱에서는 정확한데 모바일에서 아래쪽 버튼이 주소창에 가려졌습니다. 스크롤하면 보였다가, 위로 올리면 다시 가려졌습니다.

.hero { height: 100vh; }

원인 분석

모바일 브라우저에는 뷰포트 높이가 하나가 아닙니다. 주소창과 하단 바가 스크롤에 따라 나타났다 사라지므로, "화면 높이"가 상황에 따라 다릅니다.

CSS는 이를 세 가지로 나눕니다.

단위기준결과
lvh (large)브라우저 UI가 숨겨진 상태의 높이UI가 나타나면 그만큼 잘림
svh (small)브라우저 UI가 모두 보이는 상태의 높이항상 들어가지만 UI가 숨으면 여백이 남음
dvh (dynamic)UI에 따라 실시간으로 변하는 높이딱 맞지만 스크롤 중 값이 바뀜

그리고 vhlvh와 같습니다. 즉 기본값이 "주소창이 없다고 가정한 높이"라서, 주소창이 보이는 순간 100vh짜리 요소는 화면보다 커집니다. 위 증상이 정확히 이것입니다.

dvh가 만능은 아닙니다. MDN도 스크롤 도중 콘텐츠가 리사이즈되어 UI가 흔들리고 성능에도 부담이 될 수 있다고 명시합니다.

해결 방안

  1. "항상 잘리지 않아야 한다"면 svh를 씁니다. UI가 숨으면 아래에 여백이 생기지만, 콘텐츠가 가려지는 것보다는 낫습니다.
.hero { height: 100svh; }
  1. 정확히 화면을 채워야 하는 앱 셸이라면 dvh를 씁니다. 스크롤이 없는 고정 레이아웃이면 리사이즈 문제가 애초에 생기지 않습니다. 이 프로젝트의 글쓰기 화면이 그 경우로, 한 화면에 딱 맞춰야 해서 calc(100dvh - 헤더 높이)를 씁니다.
  2. 헤더 높이를 뺄 때는 실제 점유 높이를 뺍니다. 보더가 있으면 그것까지 포함해야 1px 스크롤이 생기지 않습니다.
.app-shell { height: calc(100dvh - var(--header-height)); }
  1. min-height와 height를 구분합니다. min-height는 바닥선이라 콘텐츠가 길면 그만큼 늘어납니다. "한 화면에 가둔다"가 목적이면 height여야 합니다.
  2. 가로 축에도 같은 단위가 있습니다. svw/lvw/dvw, 그리고 논리 축 버전인 svi/svb 등도 같은 규칙을 따릅니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.