[UI/UX] 모바일 디바이스 
UI/UX 최적화

tech-hoon·2022년 4월 2일
4
post-thumbnail

PC와 태블릿, iOS, android 그리고 PWA 등 다양한 디바이스 환경에서 균일한 UI와 앱처럼 편리한 UX를 제공하기 위해 적용한 것들을 공유한다.

viewport 설정

viewport란 웹페이지가 사용자에게 보여지는 영역을 말한다. 유저마다 다양한 크기의 디바이스에서 접속하다 보니, 그에 맞는 viewport를 지정해주어야 한다. html5 기본 snippet으로도 제공하는 meta 태그이다.

<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
  • meta name=”viewport”: viewport 선언
  • content=”width=device-width”: 콘텐츠를 표현할 넓이를 디바이스 크기에 맞춘다
  • initial-scale=1: 초기 크기 설정 (기본 꽉찬 화면)
  • minimum-scale=1: 최소 크기 설정 (기본값: 0.25, 범위: 0~10.0)
  • maximum-scale=1: 최대 크기 설정 (기본값: 0, 범위: 0~10.0)
  • user-scalable=no: 사용자 단말의 확대기능 사용 유무 선언 (yes/no)

y축 스크롤 고정

이미지 캐러셀이 아닌 경우, 보통 y축으로만 스크롤 하기 때문에 x축은 화면의 크기를 넘어갈 경우가 거의 없다.

body {
	touch-action: pan-y
}
  • touch-action : 어떤 요소 내에서 브라우저가 터치할 액션의 목록을 지정한다.
  • pan-y: 특정 객체를 터치한 후, 수직 혹은 수평 방향으로만 스크롤의 범위를 제한한다. 이를 적용할 시, y축으로만 스크롤을 제한하여 세로로 스크롤 중에, x축으로 화면이 이동하는 것을 방지할 수 있다.

참고: https://wit.nts-corp.com/2021/07/16/6397

상태표시줄 색상 지정

meta name='theme-color' : 상태표시줄 색상을 지정하는 meta태그 중 한 종류이다.

<meta name='theme-color' content='YOUR_COLOR'/>

모달창을 띄울때 상태표시줄 색상만 튀기 때문에, 모달시 dim된 색상으로 meta 태그를 바꿔주도록 했다. (react-helmet 이용)

<meta name='theme-color' content={modalOpened ? '#7C7C7C' : 'THEME_COLOR'} />

iOS safari 주소 표시줄 색상 지정

일반 상황에서는 앞선 theme-color로 지정한 색상이 적용되지만, PWA에서 full-screen를 적용하기 위해 manifest full-screen으로 설정한 경우, 화면이 상태표시줄까지 꽉찬 사이즈로 적용되고, 이 때 상태표시줄의 색상을 지정하는 iOS 전용 meta태그이다.

manifest.json

{
	"name": "YOUR_APP",

			...

	"display": "full-screen"
}

index.html

<meta name="apple-mobile-web-app-status-bar-style" content="#ffffff">

더블클릭/터치시 글자 영역 선택 방지

PC에서 특정 element에 더블클릭을 하거나, 더블터치를 하게 되면, 다음과 같이 block이 생기는 걸 볼 수 있다. 이는 텍스트에서는 유용하지만, 연속적인 터치가 필요하거나 이미지인 경우 몰입감을 저해할 수 있어 보인다.

이는 user-select: none으로 간단하게 처리할 수 있다.

.your_img {
	user-select:none
}

iOS safari X 100vh

PC나 안드로이드 환경에서는 height에 100vh를 적용할 시, 화면 뷰포트에 꽉차게 적용된다. 하지만 iOS safari 특성상 상단바와 하단바까지 포함한 값으로, 상단바나 하단바가 켜져있을 경우 정확한 height를 나타낼 수 없다.

hook을 만들어, 화면 크기가 resize될 때마다 변경된 화면 높이의 크기 맞게 vh를 설정해주었다. 잦은 resize로 성능에 문제가 생길 수 있기 때문에 debounce 처리를 해주었다.

import { debounce } from 'lodash';
import { useEffect } from 'react';

const useScreenHeightResize = () => {
  const handleResize = debounce(() => {
    const vh = window.innerHeight * 0.01;
    document.documentElement.style.setProperty('--vh', `${vh}px`);
  }, 500);

  useEffect(() => {
    handleResize();
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
};

export default useScreenHeightResize;

이를 지원하지 않는 브라우저에서는 100vh를 적용하고, 지원하는 브라우저에서는 받아온 --vh로 height를 설정해준다.

.container {
	height: 100vh; // fallback
	height: calc(var(--vh) * 100);
}

참고: https://velog.io/@edie_ko/Tip-모바일-브라우저에서-100vh-적용-오류-해결-iosandroid

iOS select 태그 style reset

iOS에서 select 태그의 기본 설정이 적용되어 있어서, 스타일링을 해도 적용되지가 않는다. 다음과 같이 기본 select 태그의 기본 설정을 제거해 주어야 한다.

GloabalStyles.tsx

select {
	-webkit-appearance: none;
  -moz-appearance: none; 
  appearance: none;
}

참고: https://m.blog.naver.com/sudoku1/221413644751

iOS에서 터치 시 생기는 테두리 영역 제거

iOS에서 element를 터치할 시, 터치한 element의 영역에 회색 테두리가 생긴다. 이는 터치한 영역을 사용자에게 알려줄 수 있는 장점이 있긴 하지만, 필자는 앱처럼 자연스럽게 보이는 걸 목표로 하기 때문에 이를 제거해주었다.

* { 
	-webkit-tap-highlight-color:transparent;
}

모달창 열려있을 때 스크롤 방지

모달창이 열려있을 때, 외부로 스크롤이 되는 것을 방지하기 위해, 다음과 같이 modal_opened 클래스를 동적으로 추가하고 삭제해주도록 작성한다.

body {
  overflow: auto; 
}

body.modal_opened {
  overflow: hidden; // 스크롤 방지
  touch-action: none; // 확대, 축소 비활성화
}

이미지 드래그 방지(Ghost Drag)

이미지 위에서 드래그 및 터치를 할 시 드래그 잔상이 생긴다. 이는 특히 이미지 슬라이드에서 불편한 UX를 제공한다. 다음과 같이 간단하게 개선할 수 있다.

.your_img {
	-webkit-user-drag: none;
  -khtml-user-drag: none;
  -moz-user-drag: none;
  -o-user-drag: none;
  user-drag: none;
}

모바일 hover (CSS로 PC, 모바일 구분하기)

hover 이벤트는 PC 환경에서만 발동해야 한다(정확히는 마우스). 하지만 hover 이벤트가 없는 모바일 환경에서도터치를 하면 hover에 적용된 속성이 발동한다. 이는 다음과 같이 적용하면, CSS에서 PC와 모바일을 구분할 수 있고, 따라서 괄호 안에 포함되는 스타일은 모바일 환경에서만 적용되는 스타일로 생각하면 된다.

@media (hover: hover) and (pointer: fine) {
    button:hover {
      transform: scale(150%);
    }
  }
  • hover:hover : 기본 포인팅 장치가 특정 엘리먼트 위로 쉽게 hover할 수 있는 경우를 나타낸다.
  • pointer:fine : 마우스와 같은 포인팅 장치의 존재 여부를 판별하는데 사용된다.

참고: https://paperblock.tistory.com/164

느낀점

프로덕트에 애정을 가지고 개발하고, 사용자 레벨에서 사용하다 보면 사소한 것들도 눈에 띄곤 한다. 그러면서 눈에 띄는 것들을 하나하나 개선하게 된 것 같다.

특히 PC에서 개발자 도구로 디버깅 하다보면, 실제 모바일 환경과 다소 다른 점이 발견되어 적잖이 당황했다.

그 이후로는 사용하는 아이폰과 안드로이드 직접 연결하여 디버깅하는 것이 프로덕트의 UI와 UX를 향상하는 데에 많이 도움이 된 것 같다.

그리고 iOS는 너무 까다롭다

profile
제 삽질을 공유합니다.

1개의 댓글

comment-user-thumbnail
2022년 4월 11일

글 잘봤습니다. 프로덕트를 사랑하는 개발자 멋있네요.

답글 달기