모바일 키보드 감지 - mobail kibodeu gamji

[이슈] Fixed DOM과 가상 키보드

  • 2020.12.09 15:48
  • 프로그래밍/이슈 정리

[이슈] Fixed DOM과 가상 키보드

모바일 키보드 감지 - mobail kibodeu gamji
fixed dom 과 가상키보드

 

배경

모바일 웹 작업할 때 종종 가상 키보드를 사용하는 input과 특정 위치에 고정된(position 속성이 fixed 인) 요소가 함께 설계된 시안을 만나게 된다. 이 때 아래 그림처럼 사용자가 input을 포커스 했을 때, fixed 된 요소가 가상 키보드 바로 위에 위치하는 스펙을 원하는 경우가 많다.

모바일 키보드 감지 - mobail kibodeu gamji
Fixed 버튼과 가상키보드 예시

시안대로 fixed 된 요소를 만들어보면 특정 디바이스에서 예상과 다르게 가상 키보드가 fixed 된 요소를 덮어서 가리는 이슈를 발견하게 된다. 해당 이슈는 OS(iOS/Android)마다 조금씩 다르게 나타나고, iOS에서는 버전마다 조금씩 다르게 동작하여 파악하기 힘들다. 이 문서는 해당 이슈를 OS별, 세부 버전별로 살펴보고, 왜 이런 현상이 발생하는지 내부 동작을 중점적으로 설명하려고 한다.


기본 동작 원리

현상을 이해하려면 input에 포커스 될 때, 발생하는 두가지 내부 동작(강제 스크롤, viewport 설정)에 대해 이해해야 한다.

  1. input이 포커스 될 때 자동으로 특정 위치로 이동하는 강제 스크롤 동작이 어떤 조건에서, 어떤 위치로 발생하는가?
  2. 가상 키보드가 나타났을 때 viewport는 os별로 어떻게 설정되는가?

 

강제 스크롤 동작 방식

모바일 키보드 감지 - mobail kibodeu gamji
강제 스크롤 동작방식

위 그림처럼 input이 포커스 될 때 자동으로 스크롤 위치가 변경되는 경우를 본 적이 있을 것이다. 하지만 어떤 경우에는 스크롤 위치가 변경되지 않는 경우도 있다. 그렇다면 이런 강제 스크롤 동작이 언제, 어떤 기준으로 발생하는 걸까?

 

강제 스크롤이 발생하는 경우

input의 화면 내 위치에 따라 강제 스크롤 여부가 결정된다. 여기서 말하는 위치는 가상 키보드가 올라오기 전 화면이 기준이 아니라, 가상 키보드가 나타났을 상태에서 화면 기준 input 위치를 말한다.

모바일 키보드 감지 - mobail kibodeu gamji

즉, 전체 화면에서 가상 키보드를 제외한 영역(그림을 참고하면 상단 영역+하단 영역)에서 input의 위치를 의미하고 상단, 하단(가상 키보드 영역에 있을 시 하단 위치로 간주) 중 하나로 정해지고, 그 위치에 따라 강제 스크롤 동작 여부가 결정된다.

  • 강제 스크롤이 발생하지 않는 경우 : 가상 키보드가 올라왔을 때 input이 상단 영역에 있을 경우(CASE_1)
  • 강제 스크롤이 발생하는 경우 :
    • 가상 키보드가 올라왔을 때 input이 하단 영역에 있을 경우(CASE_2)
    • 가상 키보드가 올라왔을 때 input이 키보드에 가려지는 위치에 있을 경우(CASE_3)

 

강제 스크롤 동작시 이동하는 위치

이제 강제 스크롤 동작시 어떤 위치로 스크롤 되는지 알아보자. 강제 스크롤 되는 위치는 컨텐츠의 길이에 따라 각각 달라진다.

  • 컨텐츠가 긴 경우 
모바일 키보드 감지 - mobail kibodeu gamji

위 그림처럼 컨텐츠가 길어서 스크롤 될 여유가 있다면, input이 화면(전체 화면에서 가상 키보드를 뺀 영역) 중앙에 위치할 위치로 스크롤 된다.

  • 컨텐츠가 짧은 경우
모바일 키보드 감지 - mobail kibodeu gamji

전체 컨텐츠의 길이가 길지 않아 input을 화면 중앙에 위치시킬 만큼 스크롤 여유가 없을 경우에는, 스크롤이 가능한 범위에서 중앙 위치 값에 최대한 가까운 값으로 스크롤 된다.

강제 스크롤 동작이 발생하는 이유

공식 문서에서 강제 스크롤 동작이 발생하는 이유를 찾을 수는 없었지만, 추측하기로 input의 위치가 가상 키보드에 가려지거나 화면 하단에 위치할 경우 사용자가 컨텐츠를 읽을때 불편하기 때문에 자동으로 스크롤 하는 것으로 보인다.

OS별 / 버전별 viewport 설정 방식

설명하기 앞서

어떤 공식 문서에서도 가상 키보드가 있을 때 OS별, 버전별 viewport 설정에 관한 내용을 찾을 수 없어서, 이 문서에서는 다음과 같은 추론을 통해 OS별, 버전별로 viewport 영역이 다르게 설정됨을 추측하였다.

  • 보통 viewport는 우리가 보는 화면대로 설정된다.
  • position 속성이 fixed로 설정된 요소는 viewport 기준으로 위치하게 된다.
  • 가상 키보드가 있을 경우 fixed 요소의 위치가 달라졌다. 또한 OS별, 버전별로 그 위치는 달랐다.

OS별 비교

Android
모바일 키보드 감지 - mobail kibodeu gamji

viewport 설정

안드로이드 OS는 전체 화면에서 가상 키보드 부분을 뺀 영역(위 그림에서 노란색 영역)을 viewport로 설정한다. 따라서 fixed 요소가 가상 키보드 위에 위치한다.

가상 키보드가 올라온 상태에서 스크롤 동작

모바일 키보드 감지 - mobail kibodeu gamji

스크롤 동작에 따라 viewport 영역이 변하지 않기 때문에,

fixed 요소의 위치는 변동되지 않고 고정된다.

iOS

iOS는 viewport가 정해지는 방식, 가상 키보드가 있을 때 스크롤 방식이 안드로이드 OS와 다르게 동작하고 또한 iOS 버전에 따라서도 조금씩 다르다. iOS 공통적인 특징은 가상 키보드 영역이 viewport 설정에 영향을 미치지 않고, viewport 영역을 덮는 형태로 위치한다.

10.1 버전

viewport 설정

10.1 버전은 viewport가 컨텐츠의 길이에 따라 정해지고, 가상 키보드가 올라온 상태에서 스크롤 동작시, viewport가 변하지 않는 특징이 있다.

  • 컨텐츠가 짧은 경우
모바일 키보드 감지 - mobail kibodeu gamji

그림과 같이 컨텐츠가 짧을 경우(컨텐츠 height가 디바이스 height보다 짧을 때) 화면 전체 영역이 viewport로 설정된다. 이렇게 정해진 viewport를 기준으로 fixed 요소가 위치하고 가상 키보드 영역은 컨텐츠 위로 덮는 것처럼 동작하기 때문에 fixed 요소는 가상 키보드에 가려지게 된다.

  • 컨텐츠가 길 경우
모바일 키보드 감지 - mobail kibodeu gamji

그림과 같이 컨텐츠가 길 경우(디바이스 height보다 길 때), 컨텐츠 전체가 viewport로 설정된다.

가상 키보드가 있는 상태에서 컨텐츠를 스크롤 할 경우

모바일 키보드 감지 - mobail kibodeu gamji

스크롤 동작시 fixed 요소가 마치 static 요소처럼 컨텐츠에 고정되에서 위치한다. 하지만 처음 정해진 viewport 영역이 스크롤 동작에 따라 변하지 않기 때문에, fixed 요소가 static 한 것처럼 보이는 것이다. CASE_3 처럼 최하단 위치로 스크롤하면 fixed 요소를 확인 할 수 있다.

 10.3 이후 버전
모바일 키보드 감지 - mobail kibodeu gamji

10.3 버전부터는 다른 방식으로 viewport가 설정되고, 스크롤 동작시 viewport 가동 범위가 있기 때문에 다소 복잡한 동작이 이루어진다. CASE를 통해 함께 살펴보자.

위로 스크롤 하는 경우

모바일 키보드 감지 - mobail kibodeu gamji
  • CASE_1: 10.3 버전부터는 가상 키보드 유무에 상관없이 화면 전체(노란 영역)를 viewport로 설정한다. 따라서 bottom으로 fixed 된 요소는 viewport 하단에 위치하게 된다.
  • CASE_2, 3: 위쪽으로 스크롤 시, 컨텐츠 영역과 viewport 영역(노란 영역)이 동시에 스크롤 되기 때문에 fixed 요소도 같이 움직이게 된다.
  • CASE_4, 5: viewport 가동범위 최대 y값(상단 빨간선)을 초과해서 위쪽으로 계속 스크롤 될 경우, 컨텐츠 영역은 계속 스크롤 되지만 viewport는 최대 y값에 고정된다. 따라서 컨텐츠는 스크롤 되는 상황에서 fixed 요소는 고정된 것처럼 보이게 된다.

아래로 스크롤 하는 경우

모바일 키보드 감지 - mobail kibodeu gamji
  • CASE_6, 7: 하단으로 스크롤시, 컨텐츠와 viewport 영역이 동시에 이동한다. 따라서 fixed 요소가 가상 키보드에 다시 가려지게 된다.
  • CASE_8, 9: 하단으로 계속 스크롤하다 viewport 가동범위 최소 y값(하단 빨간선)에 도달하면 컨텐츠 영역은 계속 스크롤 되고, viewport는 최소 y값에 고정된다. 따라서 컨텐츠는 스크롤 되는 상황에서 fixed 요소는 고정된 것처럼 보이게 된다.
  • CASE_10: 다시 위쪽으로 역방향으로 스크롤시, viewport 가동범위 최대 y값에 도달하지 않았기 때문에 컨텐츠 영역과 뷰포트 영역이 함께 스크롤 된다. 따라서 fixed요소 viewport와 함께 움직인다.
앱 내장 브라우저

앱에 내장된 브라우저(ex.works mobile, line, 카카오톡)마다 동작이 다르다. 이 문서에서는 실무와 관련이 깊고 다소 특이한 방식으로 동작하는 works mobile 내장 브라우저에 대해 살펴보려고 한다.

안드로이드는 기본 브라우저와 동일하게 동작하지만, iOS의 경우 알아본 것과 다르게 동작한다.

iOS
모바일 키보드 감지 - mobail kibodeu gamji
  • viewport 설정
모바일 키보드 감지 - mobail kibodeu gamji

가상 키보드 유무에 상관없이 화면 전체(노란 영역)을 viewport로 설정한다. 따라서 bottom으로 fixed 된 요소는 viewport 하단에 위치하게 된다.

  • 스크롤에 따른 동작
모바일 키보드 감지 - mobail kibodeu gamji

10.3 버전과는 다르게 viewport 최소, 최대 가동범위 제한이 없기 때문에 컨텐츠와 viewport가 함께 스크롤 된다. 그렇기 때문에 fixed된 요소도 스크롤 된다.

해결 방법

iOS

iOS의 경우 가상 키보드 관련 이벤트를 감지 할 수 있는 방법이 없다. 이전 버전에서는 가상 키보드의 크기가 고정되어 있어 어느 정도 대응 할 수 있었지만, iOS 버전이 올라가면서 디바이스마다 가상 키보드의 크기가 달라졌다. 또한 사용자가 설정한 기능(자동 완성, 커스텀 키보드)에 따라서도 달라질 수 있어서 이슈를 대응할 수 없는 상황이다.

Android

Android는 가상 키보드가 올라왔을 때, resize 이벤트를 통해 viewport의 height를 계산할 수 있기 때문에 어느 정도 대응이 가능하다. 하지만 화면이 landscape모드로 가로 회전 되었을 때, 이슈가 있어 완벽한 대응은 어려운 상황이다.

절충안

앞서 알아본 것 처럼 키보드 input을 사용하는 디자인의 경우 input의 스크롤 위치, 디바이스의 해상도, OS 및 버전에 따라 결과가 달라진다. 허무하지만 현재 이를 해결할 수 있는 완벽한 방법은 아직 없기 때문에 input을 사용해야 할 경우 fixed 된 요소와 함께 사용하는 것을 지양하고, 반드시 사용해야 한다면 input과 최대한 가깝게 위치시키는 방식으로 설계 자체를 변경하는 하는 것이 이슈를 최소화 할 수 있는 방법이다.

글이 도움이 되셨다면 공감&댓글 부탁드립니다.
글 작성에 큰 힘이 됩니다. 🙂