안녕하세요. 감성 UI를 좋아하는 김성훈입니다.
일본 라인 앱 서비스인 LINE 변호사상담 프로젝트를 진행하면서 진행한 아이폰X 해상도 대응 내용 공유드립니다.
읽기 편하게 그림 많이 넣었으니 가벼운 마음으로 정독(?)해 주세요.
1. 안전영역(Safe Area)이란?
Safe Area는 원래 TV에서 처음 도입된 개념입니다.
TV 해상도 비율이 다양해지면서 영상에서 타이틀, 자막 등이 필수 콘텐츠의 노출을 보장할 수 있는 영역입니다.
보통 오래된 TV 해상도가 가진 4:3 비율 기준으로 타이틀, 자막 등이 모두 노출되게 작업을 했습니다.
TV Safe Area (http://www.indefilms.net/html/title_safe_area.html)
2. 왜 아이폰X는 Safe Area가 필요할까요?
아이폰8 이하 기종과 달리 아이폰X의 디스플레이 영역은 상/하단 라운드 영역을 포함하고 있습니다.
추가적으로 상단 영역은 카메라, 스피커 등의 센서가 있는 노치(notch)가 존재하여 콘텐츠가 제대로 노출될 수 없습니다.
그래서 아이폰X은 안정적으로 콘텐츠가 보일 수 있는 Safe Area를 가지고 있습니다.
아이폰8, 아이폰X 화면 영역 비교 (http://blog.rightbrain.co.kr/?p=8499)
iPhone Xs(v12.3.1) Safe Area
3. Safe Area 문제점
기본적으로 아이폰X 화면 상단은 앱 또는 브라우저가 가지고 있는 내비게이션 고정 영역이 있으므로 Safe Area를 크게 신경 쓸 필요는 없습니다.
하지만 좌/우/하단 영역의 경우 아이폰X과 그 외 디바이스에서 보이는 게 다를 수 있습니다.
이해를 돕기 위해 테스트 페이지를 만들어 비교해 보았습니다.
테스트 환경 iPhone 6(v12.4.1) / iPhone Xs(v12.3.1)
위 그림에서 살펴보면 크게 2가지 문제점이 있습니다.
- Safe Area 밖의 margin 영역(스타일 적용 못함) 노출
- 화면 하단 홈 인디케이터 영역과 레이아웃 겹침 현상 발생
제가 진행한 프로젝트는 위 디자인 이슈가 발생하여 Safe Area 설정을 변경해야 했습니다.
4-1. 아이폰X : 전체 화면 적용
전체 화면 설정 방법은 매우 간단합니다.
뷰포트 메타태그에서 viewport-fit=cover 를 추가합니다.
참고로 viewport-fit 기본값은 auto 입니다.
<meta name='viewport' content='initial-scale=1, viewport-fit=cover'>
iPhone Xs(v12.3.1) viewport-fit=cover 적용
4-2.아이폰X : env() 속성 적용
전체 화면을 적용 시 아이폰X의 노치 영역과 하단 인디케이터 영역까지 모두 사용하므로 콘텐츠가 잘리거나 겹쳐 보이는 문제점이 발생할 수 있습니다.
그래서 아이폰X에서 사용 가능한 CSS 속성인 env() 를 제공하고 있으며 4개의 변수 적용이 가능합니다.
참고로 env() 는 아이폰X에서만 동작하므로 그 외 디바이스에는 영향을 주지 않습니다.
(* iOS 11에서 제공하는 동일한 속성인 constant() 가 11.2 버전부터는 제거되고, env() 로 대체되었기 때문에 하위 버전 대응이 필요하다면 constant() 도 같이 적용해주어야 합니다.)
// iOS 11.0 버전 constant(safe-area-inset-top) constant(safe-area-inset-right) constant(safe-area-inset-bottom) constant(safe-area-inset-left) // iOS 11.2 이상 env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)
env() 지원 범위 (https://caniuse.com/#search=env)
적용 예시 1
iPhone Xs(v12.3.1) 세로 모드
.btn { padding: 15px 0 calc(constant(safe-area-inset-bottom) + 15px); padding: 15px 0 calc(env(safe-area-inset-bottom) + 15px); }
적용 예시 2
iPhone Xs(v12.3.1) 가로 모드
.wrap { padding-right:constant(safe-area-inset-right); padding-left:constant(safe-area-inset-left); padding-right:env(safe-area-inset-right); padding-left:env(safe-area-inset-left); } .btn { padding: 15px 0 calc(constant(safe-area-inset-bottom) + 15px); padding: 15px 0 calc(env(safe-area-inset-bottom) + 15px); }
calc() 를 이용하면 아이폰X 이외 디바이스는 safe-area-inset 를 제외한 나머지 값만 적용됩니다.
5.아이폰X의 safe-area-inset margin
마지막으로 위 예시 화면을 살펴보면 세로 모드와 가로 모드일 경우 하단 safe-area-inset 의 margin 이 다른 것을 확인할 수 있습니다.
각 모드에 따른 safe-area-inset 의 margin 이 궁금해집니다.
아래 테스트 화면 참고하세요.
iPhone Xs(v12.3.1) 가로/세로 모드 safe-area-inset margin
읽어주셔서 고맙습니다.
다음에 또 재미난 글로 찾아오겠습니다.
4개의 댓글
Jaden · 2020년 2월 21일 10:12 오전
이런 고민을 해야한다니 정말 어렵네요. 프론트엔드 개발이나 설계는 어렵기도 하지만, 까다롭다는 생각이 많이 듭니다.
에스프레소 · 2020년 4월 1일 6:43 오후
뷰포트 언급해 주신것 너무 감사합니다. 웹뷰를 사용한 화면인데 하단에 허옇게 나온거 어찌 해결할지 머리만 아팠는데 해결해 주셨습니다.
ZKDEV · 2020년 12월 16일 8:16 오후
현재 iOS 14.3의 사파리는 위의 적용과 미적용이 반대로 표시될 수 있습니다. 반대로 노치부분을 강제로 다 적용하고, 위와같이 알고 사용하면 노치부분에도 어색하지 않게 꾸밀 수 있겠네요.
문제는 iOS의 크롬이네요. 이건 다 버그네요. landscape로 돌리면 곤혹스롭게 상하 여백이 나오고 다시 portrait로 돌아오면 그 여백이 좌우로 다시 모두 붙네요.
노치 없는 구형 아이폰에서 이런 현상이 없는 것 보니 노치와 관계된 것으로 추측한데, 크롬은 이것을 거꾸로 적용하고 있는 것 같네요. 모든 웹사이트 모바일 페이지를 현재 좌우로 넓게 돌렸다가 다시 돌아오면 좌우에 새로운 모두 여백이 붙어 있는 이상한 현상을 보이고 있는데요.
이건 구글에서 해결해야할 것이지 웹상에서 개발로 할 수 있는 부분이 아닌 것 같습니다. 그래서 크롬을 자주 사용하니 이거 참 곤혹스럽긴 하네요. 참고로 주소 입력창을 클릭하고 돌아오면 제대로 다시 돌아옵니다.
걱정하지않는자 · 2022년 4월 30일 9:02 오후
귀한 정보 감사합니다. 덪붙이자면 실제 앱에서만 safearea 값이 적용되며, 사파리 웹에서는 safearea 값이 적용 안되는 점 참고 바랍니다.