next.js를 capacitorjs를 이용해 앱으로 만드는 작업을 하면서 알게 되었다.
웹페이지와 달리 모바일 환경에서는 상하단에 노치(notch) 영역이 존재한다. 그래서 예를 들어 상단에 fixed top-0(편의상 tailwind CSS 클래스를 사용한다고 가정)으로 고정된 요소가 노치 영역과 겹치는 문제가 발생할 수 있다.
이를 해결하는 하나의 방식으로 env() CSS 함수가 있어 간략히 학습하였다.
env() 함수는 환경 변수에 정의된 값을 CSS에 삽입할 때 사용할 수 있다. CSS 변수(--*, var())와 다른 점은 이런 환경 변수는 브라우저나 운영체제 즉 사용자 에이전트에서 정의한다는 것
대표적으로 ios 브라우저에서 뷰포트의 상단, 하단 노치에 가리지 않고 안전하게 표시될 수 있도록 safe-area-inset-top, safe-area-inset-bottom 등의 환경 변수를 제공한다.
사각형이 아닌 화면에서 내용이 잘릴 있는 스마트폰 등의 화면에서는 이런 환경 변수를 이용해 padding을 주어 사각형 화면에서처럼 안전하게 표시되도록 할 수 있다.
/* 사각형 뷰포트에서는 전부 0 */
env(safe-area-inset-top);
env(safe-area-inset-right);
env(safe-area-inset-bottom);
env(safe-area-inset-left);
/* 다음과 같이 대체 값도 제공 가능 */
env(safe-area-inset-top, 16px);
이외에도 데스크탑 pwa에서 상단의 os 영역을 차지할 때 닫기 버튼 등과 겹치는 문제를 해결하기 위해 titlebar-area-*라는 환경변수, 가상 키보드 관련 virtual-keyboard-* 환경변수 등이 존재한다.
pwa에서 window controls api와 함께 사용하는 것에 대해서는 env() 를 사용해 데스크탑 PWA에서 컨텐츠가 창 제어 버튼에 의해 가려지지 않도록 보장하기 문서 참고. 위에서 언급한 대로 titlebar-area-* 를 사용한다.
요구조건 #
브라우저에서 화면의 전체 공간을 사용하고 env() 변수를 사용할 수 있게 하려면 다음과 같은 뷰포트 값을 추가해야 한다.
<meta name="viewport" content="viewport-fit=cover" />
사용예시 #
예를 들어 헤더가 상단에 고정되어 있고, 노치 영역과 겹치는 문제를 해결하기 위해 다음과 같이 작성할 수 있다.
.header {
/* 좌우 패딩, position css 등 다른 값도 들어갈 수 있을 것 */
padding-top: env(safe-area-inset-top);
}
padding에 많이 적용하는 거 같고, 추가적인 패딩이 필요할 경우(예를 들어 헤더의 기본 패딩이 16px이라면) calc() 함수를 이용해 다음과 같이 작성할 수 있다.
.header {
padding-top: calc(env(safe-area-inset-top) + 16px);
}
참고 #
MDN env() 문서 https://developer.mozilla.org/ko/docs/Web/CSS/Reference/Values/env
CSS 아이폰 안전영역(safe area) 대응 : 아이폰 노치 대응 https://velog.io/@leejpsd/CSS-아이폰-안전영역safe-area-대응-아이폰-노치-대응