← 전체 글로 돌아가기

Flutter

모바일 Safari에서 100vh가 화면을 넘칠 때 바꾼 레이아웃 기준

iPhone Safari에서 하단 버튼이 주소창 뒤로 밀렸다. 100vh 대신 동적 뷰포트 단위를 적용하며 정리한 짧은 튜토리얼.

하단 버튼이 보이는데 누를 수 없었다

로그인 페이지를 휴대폰에서 열었을 때 하단 버튼 일부가 Safari 주소창 아래로 들어갔다. 데스크톱의 기기 모드에서는 멀쩡해서 padding 문제라고만 생각했다. 실제 기기에서 주소창이 접히고 펼쳐질 때 100vh의 기준이 화면 높이와 다르게 동작한 것이 원인이었다.

높이 단위의 역할을 구분했다

모바일에서 vh는 브라우저 UI를 포함한 큰 뷰포트를 가리킬 수 있다. 화면에 보이는 영역에 맞추려면 dvh가 더 적합하다. 주소창이 접혀도 레이아웃이 다시 계산된다.

.auth-page {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: 1fr auto;
}

앞 줄은 dvh를 모르는 브라우저를 위한 fallback이다. 고정 높이보다 min-height를 쓴 이유는 오류 문구가 늘거나 글자 크기를 키웠을 때 내용이 잘리지 않게 하려는 것이다.

안전 영역도 별도로 처리했다

홈 인디케이터 근처에 버튼이 있으면 아래 여백은 화면 높이와 다른 문제다.

.bottom-actions {
  padding-bottom: max(16px, env(safe-area-inset-bottom));
}

처음에는 모든 페이지에 이 여백을 넣었는데, 일반 목록까지 불필요하게 넓어졌다. 화면 가장자리에 고정된 조작부에만 적용하는 기준으로 바꿨다.

실제 기기 확인 체크리스트

  • 주소창을 접고 펼쳐 본다
  • 키보드를 열어 입력창과 버튼이 가려지지 않는지 본다
  • 글자 크기를 크게 한 상태에서도 스크롤이 가능한지 본다
  • iOS와 Android에서 각각 한 번 확인한다

뷰포트 문제는 CSS 한 줄로 끝나는 듯하지만, 결국 사용자가 손가락으로 닿을 수 있는지를 보는 일이었다.