퍼블을 하다보면 화면을 가득 채우거나, 밑부분쪽에 콘텐츠를 채워야 하는 경우가 생긴다. 이번에 나는 Bottom Sheet를 구현해야 하는 상황이었다.
그럴 경우 100vh를 사용해서 처리를 하게 되는데,, 이것이 모바일로 가면 다음과 같은 문제가 생긴다.
<div style={{ top: `calc(100vh - 60px)` }} >
크롬에서는 딱 붙어서 나오는데, 사파리에서는 저 미친 도구 영역에 가려서 보이지 않는다. 이게 왜 그런가 확인해봤더니,, 사파리는 100vh 기준이 저 URL 영역까지 포함하는 것이었다. (그 아래 도구툴 영역은 포함X)
살짝 위로 땡겨보면 렌더는 되고 있는데 100vh이 주소창까지 먹히는 것을 확인할 수 있다. 왜.. 이렇게 만들었지? 하는 순간 음 그럴 수밖에 없겠구나 했다. 그 이유는 사파리는 스크롤에 따라 화면 영역을 다이나믹하게 대응하기 때문.
지금 보니 네이버는 요거에 대한 대응을 해놨군 역시 네이버 ...
검색해보니 여러 방법이 나왔는데, 일단 일반적인 방법은 다음과 같은 것 같다.
const { innerHeight } = window;
document.documentElement.style.setProperty('--vh', `${innerHeight * 0.01}px`);
.full-page {
min-height: calc(var(--vh, 1vh) * 100);
}
이 방법은 vh단위를 새로 지정하는 방법이다. 실제 렌더된 화면 크기를 구한 다음, 그 크기의 1/100을 CSS 변수로 등록하고 쓰는 방법. (1vh가 viewport의 1/100이니까)
var() 함수의 두 번째 인자는 첫 번째의 변수가 유효하지 않을 때 대체할 수 있는 값을 의미한다.
하지만,, 이 방법은 위에서와 같이 다이나믹하게 변하는 Safari Browser에 대응하지 못한다. 반쪽짜리 정답. 그렇다고 스크롤할 때마다 다시 구해준다? 0점짜리...
이 속성은 웹킷 CSS 속성값이다. 어떤 속성값이냐면 해당 객체가 채울 수 있는 최대한의 공간을 다 쓰는 속성값인데,, 일단 쓰는 방법은 다음과 같다.
height: -webkit-fill-available;
포인트는 이 값은 Safari의 URL 영역까지 포함시키지 않는다는 것. 그래서 원하는 결과를 낼 수 있지만 ,,, !! 이 값은 calc()로 다른 값과 계산하지 못하며, 호환성에 대한 문제가 있어서 fallback을 해주어야 하며, 살펴보니 특정 상황에서 잘 작동하지 않는다는 사례도 좀 있던 것 같다.
어디까지나 webkit vender이므로,, 쓰는 것은 잘 고려해보아야 한다.
100vh에 대한 문제를 인지하고 있었던지, 2022년도에 CSS에 새로운 Viewport 단위가 등장했다(!)
svw, svh 작은 뷰포트 각각의 너비 및 높이 1%.
lvw, lvh 큰 뷰포트 각각의 너비 및 높이 1%.
dvw, dvh 동적인 뷰포트 각각의 너비 및 높이 1%.
출처: CSS 값과 단위(MDN)
Short Viewport : 확장하기 위해 동적으로 확장되고 접히는 모든 UA 인터페이스(예: 주소 표시줄)를 가정한 뷰포트 크기
Large Viewport : 접기 위해 동적으로 확장 및 접히는 UA 인터페이스(예: 주소 표시줄)를 가정한 뷰포트 크기
Dynamic Viewport : 모든 UA 인터페이스를 동적으로 고려하는 뷰포트 크기입니다. 표시되는 UA 인터페이스 요소에 따라 자동으로 조정됩니다. 값은 100lvh(최대) 및 100svh(최소)의 내에 있습니다.
내 식대로 이해하자면, svh는 도구 영역이 다 펼쳐져 있을 때의 크기이고, lvh는 도구 영역이 가려졌을 때의 크기, 그리고 dvh는 스크롤에 따라 변하는 영역까지 대응하는 크기인 것.
그래서 dvh를 이용해서 해결할 수 있었다.
<div style={{ top: `calc(100dvh - 60px)` }} >
이 방법은 URL창이 아래에 있든 위에 있든 다 동작한다. ヾ(•ω•`)o