모바일 하단 고정 레이아웃 이슈

하단 고정 레이아웃

  • 아래와 같이 html, css 를 작성하면 해당 영역은 하단에 고정된다.
<div id="wrap">
	<div class="contents">컨텐츠 영역</div>
	<div class="fixed">
		<input type="text">
	</div>
</div>
.fixed{
	height:100px;
	width: 100%;
	position: fixed;
	left: 0;
	bottom: 0;
}

화면상 하단에 특정 요소를 상시 고정시켜 주는 방법으로 중요한 컨텐츠나 사용자가 빠르게 접근해야할 요소를 스크롤과 관계없이 display 를 기준으로 고정시켜 주기 때문에, UI상으로 아래와 같을때 자주 사용된다.

  • 현제 페이지를 알리는 제목
  • 다른 페이지나 카테고리로 이동할 수 있는 메뉴 버튼(햄버거 버튼 등)
  • 현재 페이지를 공유 하는 공유하기 버튼
  • 카테고리나 사이트 메뉴 중 중요한 메뉴만 특정영역에 고정시킴
  • 커머셜 사이트에서 제품 상세 페이지의 옵션선택 영역

누군가 그랬다.
web 을 app 처럼 만들려고 하기 때문에 문제가 발생한다
분명 내가 처음 모바일 웹 사이트를 제작할 당시만 해도 하단고정 에 대해서는 기술적으로 구현이 까다로운 편에 속했다.(당시 모바일 기기의 브라우저에서 하단 고정(position:fixed; bottom:0)을 지원하지 않았다.)
하지만 지금 포스팅 하고 있는 이 시점에 대부분의 모바일 기기에 포함되거나 설치되는 브라우저는 하단고정을 지원하고 있다.
나의 경우는 커머셜 사이트에서 제품 상세 페이지의 옵션선택 기능을 하단 고정영역에 위치 시킴으로써 문제가 발생했다.

Issue 1

하단 고정영역에 있는 form 요소
문제는 IOS safari 에서 발생했고 테스트 디바이스는 iphone 5s / iOS 8.3 이었다. 증상은 하단 고정영역의 form 요소를 터치 했을때, iOS 의 기본 UI(키보드, 셀렉트박스 등)가 하단에서 올라오면서 스크롤이 html 문서상 form 요소의 위치로 강제 이동되는 것 이었다.

결론부터 얘기 하자면, 해결 방법은 없다.
fixed 속성을 absolute 로 변경하고, 스크롤값이 변경될 때마다 해당 요소의 top 값을 갱신해 주면 가능은 하지만 자연스럽지 않은 모습을 보여주게 된다. 또한 UI자체가 하단에서 위로 올라오면서 열리는 방식이었으므로 구현은 더 복잡할 수 밖에 없었다. 우리는 기본 form 요소를 버리고, layer등을 문서 위로 띄워 조금 다른 UI로 사용자에게 보여주기로 했다. 이 문제는 iPhone 에서만 발생했다(iPad 도 동일할 것이다.).

Issue 2

하단 고정영역 밖에 있는 form 요소 이 문제는 조금 복잡하다.
컨텐츠 중간에 fomr 요소가 있고, 하단엔 여전히 고정된 요소가 붙어 있다. 사용자가 문서 중간에 들어가 있는 form 요소를 터치하면 당연히 포커스가 이동되면서, 기기의 기본 UI 가 하단에서 올라오거나 화면중간에 뜨게 된다.
이때 기기별로 아래와 같은 증상이 발생한다.

  • iOS safari 에서는 fixed 된 요소들의 fixed 속성을 제거한다.(문서상의 원래 위치로 돌린다.)
  • iOS 의 web view(native app 내에 삽입되는)에서 fixed 된 요소들은 webview 영역 상에서 fixed 를 유지해 스크롤시 화면기준으로 top, bottom 을 갱신하지 않는다.(마치 화면기준 absolute 를 띄운듯하다.)
  • android 의 기본브라우저에서는 화면의 resize 가 발생한다. 키보드 위로 fixed 요소가 올라온다.(경우에 따라 form 요소를 가린다.)
  • android 의 chrome 에서도 기본브라우저와 동일한 이슈가 발생한다.

클라이언트의 요청은 이러했다.

  • 키보드, selectbox 등의 UI가 화면을 치고 올라올때, 고정요소가 화면을 가리지 말것.
  • iOS web view 영역의 이슈를 해결할것.

첫번째 요청을 처리하기 위해 다음과 같은 사항을 인지하고 있어야 했는데..
iOS 의 UI는 다음, 완료, 검색 등의 버튼을 누르지 않는 이상 사라지지 않는다. 그리고 해당 버튼을 누르는 순간 blur 이벤트가 발생한다.
안드로이드 기본브라우저는 selectbox UI가 올라온 상태에서 스크롤 할 경우 기본 UI가 사라진다. 문제는 blur 이벤트가 발생하지 않는다. 즉 focus 는 그대로 selectbox 에 위치 하고 있다.
selectbox 가 아닌 text, number 등 요소에 focus 가 되었을때…scroll 을 하게 되면 키보드는 사라지지 않는다. 뒤로가기 버튼(안드로이드 버튼)을 눌렀을때 키보드가 사라지는데, 그렇다고, blur 이벤트가 발생하지는 않는다. body 영역을 터치했을때 blur 이벤트가 발생한다.
안드로이드 chrome 브라우저는 화면 스크롤시 기본 UI 가 사라진다. 처음 계획은 focus 되었을때 fixed 요소를 relative 속성으로 변경해 주려고 했다.(상단이든, 하단이든 원래 위치가 존재 했으므로) 그리고 blur 이벤트가 발생했을때, 다시 fixed 요소의 속성을 원래대로 돌리는 것이다.
하지만 blur 이벤트가 발생하지 않는다면 사용자는 스크롤을 해도 하단 고전영역, 상단 고정영역을 볼 수 없을 것이다.(물론 원래 위치에 있기때문에 언젠가는 볼수 있지만 의도되지 않은 UI다.)

해결

  • selectbox , input 등 radio 와 checkbox 를 제외한 모든 form 요소에 focus 발생시 고정요소를 숨김
  • blur 이벤트 발생시 fixed 요소를 원래 속성으로 돌림.
  • selectbox 는 change event 발생 후 scroll 시 fixed 요소를 원래 속성으로 돌림.

물론 아직까지 문제는 있다.
안드로이드 기본브라우저의 selectbox 에서 change 가 일어나지 않은 상태로 스크롤 시 fiexd 요소를 원래 속성으로 돌릴 장치가 딱히 없다. 사용자가 다른 요소를 탭 하거나 혹은 body영역을 한번 더 탭해 주기를 바랄뿐…

사실 개인적으로 이번 포스팅에서 하고 싶은 말은 이것 이엇다.

작은 화면에서 고정영역은 사용성이 좋지 않다. 모바일에서 하단 고정영역은 문제가 많으며, 아직까지 처리하기 까다로우 부분이 많다. 가능하면 하단 고정 UI는 아직까지 추천하고 싶지 않다.