모바일에서 100vh는 주소창 UI에 따라 들쭉날쭉해서 풀스크린을 보장하지 못한다. 이젠 dvh / svh / lvh를 써라. 기존 --vh JS 해킹은 CSS 한 줄로 치환 가능.
모바일 웹뷰에서 height: 100vh를 주면 스크롤할 때 레이아웃이 튄다. 기대치는 "화면 꽉 차게"인데, iOS Safari와 일부 안드로이드 Chrome은 주소창이 나타났다 사라지는 동안 뷰포트 높이가 바뀐다. 100vh는 주소창이 숨겨진 상태(=최대 높이) 기준으로 고정돼있어서, 주소창이 나와 있는 동안은 실제 보이는 영역보다 100vh가 더 크다. 결과적으로 하단 요소가 주소창에 가려지거나, 스크롤 시 화면이 덜컥거린다.
CSS Values and Units Level 4에서 뷰포트 단위가 네 계열로 세분화됐다.
| 단위 | 의미 | 언제 씀 |
|---|---|---|
vh | 기존 단위 (브라우저별 해석 차이 있음) | 레거시 호환 |
lvh | Largest — 주소창 숨겨졌을 때 기준 | "제일 넓을 때" 기준이 필요할 때 |
svh | Smallest — 주소창 보이는 상태 기준 | "절대 잘리지 않아야" 할 때 |
dvh | Dynamic — 현재 보이는 영역 실시간 반영 | 대부분의 실무 케이스 |
/* 풀 스크린 섹션 — 주소창에 가려지지 않게 */
.hero {
min-height: 100svh; /* 주소창 나와도 안 잘림 */
}
/* 스크롤에 따라 자연스럽게 맞추고 싶을 때 */
.fullscreen-modal {
height: 100dvh; /* 스크롤에 맞춰 갱신됨 */
}
/* fallback 포함 권장 */
.safe {
min-height: 100vh; /* 구형 브라우저용 */
min-height: 100dvh; /* 지원되면 덮어씀 */
}
너비 쪽도 dvw / svw / lvw가 짝으로 존재한다. 대부분은 높이가 문제라 덜 쓰는 편.
dvh는 자주 갱신된다 — 스크롤 중 실시간으로 레이아웃이 다시 계산되므로 height: 100dvh를 무거운 컨테이너에 걸면 성능 저하가 느껴질 수 있다. Safari에서 특히 덜컥임 보고가 있다.position: fixed 요소 주의 — fixed; bottom: 0 요소는 dvh를 쓰지 않으면 주소창 변화에 따라 잘린다.@supports로 fallback 감싸기 권장 — 구형 브라우저에서 선언이 무시되면서 높이가 0이 되는 사고 방지.--vh 커스텀 프로퍼티 + window.innerHeight 리스너 조합을 CSS 한 줄로 치환 → JS 번들 감소, resize 이벤트 리스너 제거100vh 쓰는 곳을 찾아 100svh / 100dvh로 점진 교체하면 하단 CTA 가림 이슈 대부분 해소100vh fallback을 반드시 남긴 뒤 중복 선언 또는 @supports (height: 100dvh)로 새 단위 적용 ⚠️ 실행 전 대상 브라우저 매트릭스 확인 필요