[JS] ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ๋ฅผ ํ๋ณํ๋ 6๊ฐ์ง ๋ฐฉ๋ฒ
navigator.userAgent
๋ธ๋ผ์ฐ์ API์์ ์ ๊ณตํ๋ userAgent
๋ฌธ์์ด์ ํ์ธํ๋ ๋ฐฉ๋ฒ. userAgent
๋ ์ ์ ๋๋ฐ์ด์ค์ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ navigator.userAgent
์์ฑ์ผ๋ก ์ ๊ทผํ ์ ์๋ค.
userAgent
๋ฌธ์์ด์ด mobi
, android
iphone
๋ฑ ํค์๋๋ฅผ ๋ด๊ณ ์๋ค๋ฉด ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ๋ก ์ ์ํ๋ค๊ณ ๋ณผ ์ ์๋ค. ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด์ง๋ง ์ฌ์ฉ์๊ฐ ์ง์ userAgent
๊ฐ์ ์์ ํ ์ ์๊ธฐ ๋๋ฌธ์ 100% ์ ๋ขฐํ ์ ์๋ค.
// ๋ฐฉ๋ฒ 1
// ์ ๊ท์์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ๋ค. i ํ๋๊ทธ๋ก ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์๋๋ก ํ ์ ์๋ค
if (/Mobi|Android|iPhone/i.test(navigator.userAgent)) {
// ํ์ฌ ์ฅ์น๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ
}
// ๋ฐฉ๋ฒ 2
if (
navigator.userAgent.match(/Mobi/i) ||
navigator.userAgent.match(/Android/i) ||
navigator.userAgent.match(/iPhone/i)
) {
// ํ์ฌ ์ฅ์น๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ
}
Chromium ๊ณ์ด์ ๋ธ๋ผ์ฐ์ ๋ userAgent
์ ๋น์ทํ ์ญํ ์ ํ๋ navigator.userAgentData
๋ผ๋ ์์ฑ์ด ์๋ค. ์ฐจ์ด์ ์ ์ฌ์ฉ์ ์์ด์ ํธ ๋ฌธ์์ด์ ๊ฐ์ฒด๋ก ํ์ฑํ๊ณ , ํด๋น ๊ฐ์ฒด ์์ mobile
์์ฑ์ ํตํด ์ฌ์ฉ์์ ๋ชจ๋ฐ์ผ ์ฅ์น ์ฌ์ฉ ์ฌ๋ถ๋ฅผ boolean ๊ฐ์ผ๋ก ํ์ธํ ์ ์๋ค.
const isMobile = navigator.userAgentData.mobile;
๐ก ์ ํ์ Safari์ Firefox๋ userAgentData
์์ฑ์ ์ง์ํ์ง ์๋๋ค. ์์ธํ ๋ด์ฉ์ caniuse ์ฐธ๊ณ
window.screen, window.innerWidth
์คํฌ๋ฆฐ ๋๋น๋ฅผ ํตํด ๋ชจ๋ฐ์ผ ๋๋ฐ์ด์ค์ธ์ง ํ์ธํ๋ ๋ฐฉ๋ฒ. window.screen
๊ฐ์ฒด๋ ์ ์ ๋๋ฐ์ด์ค์ ์คํฌ๋ฆฐ ์ ๋ณด๋ฅผ ๋ฐํํ๋ค(๋ชจ๋ํฐ ์ฌ์ด์ฆ). ์ด ๊ฐ์ฒด์ width
์์ฑ์ด ๋ฐ๋ก ์คํฌ๋ฆฐ ๋๋น. ์ ์ ๊ฐ ๊ฐ๋ก๋ชจ๋๋ก ํธ๋ํฐ์ ์ฌ์ฉํ๋ค๋ฉด ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์ธ์ง ์๋ณํ ์ ์๋ ๋จ์ ์ด ์๋ค.
if (window.screen.width < 500) {
// ํ์ฌ ์ฅ์น๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ
}
๋ ๋ค๋ฅธ ์์ฑ์ธ window.innerWidth
๋ ๋ธ๋ผ์ฐ์ ์ฐฝ ์์ชฝ์ ๋ทฐํฌํธ(์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๋ ์์ญ) ๋๋น๋ฅผ ๋ฐํํ๋ค. ์คํฌ๋กค๋ฐ๋ ํฌํจํ ๊ฐ์ด๋ค. ์นํ์ด์ง์ ๊ฐ ๋๋น๋ง๋ค ๋ค๋ฅธ ์คํ์ผ์ ์ง์ ํ ๋ ์ ์ฉํ๋ค.
const getBrowserWidth = () => {
if (window.innerWidth < 768) {
return "xs";
} else if (window.innerWidth < 991) {
return "sm";
} else if (window.innerWidth < 1199) {
return "md";
} else {
return "lg";
}
};
- window.screen.width / height : ๋ชจ๋ํฐ ์ฌ์ด์ฆ
- window.outerHeight / outerWidth : ๋ธ๋ผ์ฐ์ ์ ์ฒด ์ฌ์ด์ฆ
- window.innerHeight / innerWidth : ์คํฌ๋กค๋ฐ ํฌํจ ๋ทฐํฌํธ ์ฌ์ด์ฆ
- document.documentElement.clientWidth / clientHeight : ์คํฌ๋กค๋ฐ ์ ์ธ ๋ทฐํฌํธ ์ฌ์ด์ฆ
window.orientation
์คํฌ๋ฆฐ ๋ฐฉํฅ์ ๊ฐ์งํ๋ ๋ฐฉ๋ฒ. ํด๋ํฐ์ ์ธ์ ๋ ์ง ์คํฌ๋ฆฐ ๋ฐฉํฅ์ ๋ฐ๊ฟ ์ ์์ง๋ง, ๋ฐ์คํฌํ ๋ชจ๋ํฐ๋ ๊ณ ์ ์์ผ ๋๊ณ ์ฌ์ฉํ๋๊ฒ ์ผ๋ฐ์ ์ด๋ค.
window.orientation
์์ฑ์ ํ์ฌ ์คํฌ๋ฆฐ์ ๋ฐฉํฅ ๊ฐ์(๊ฐ๋) ๋ฐํํ๋ค. ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์์๋ง ํด๋น ์์ฑ ๊ฐ์ด ์กด์ฌํ๋ค. ๋ฐ์คํฌํ์์ undefined
๋ฅผ ๋ฐํํ๋ค.
if (typeof window.orientation !== 'undefined') {
// ํ์ฌ ์ฅ์น๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ
}
๐ก iPhone์ Safari ๋ธ๋ผ์ฐ์ ๋ ํด๋น ์์ฑ์ ์ง์ํ์ง ์๋๋ค.
touch ์ด๋ฒคํธ
ํด๋ํฐ ๋ธ๋ผ์ฐ์ ์ DOM ์์๋ ontouchstart
์์ฑ์ผ๋ก touch
์ด๋ฒคํธ์ ๋ํด ๋ฆฌ์ค๋ ํจ์๋ฅผ ์ง์ ํ ์ ์๋ค. ๋ฐ์คํฌํ DOM์ ontouchstart
์์ฑ์ด ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ด์ฉํด ๋ชจ๋ฐ์ผ ์ฅ์น์ธ์ง ํ๋ณํ ์ ์๋ค.
// ๋ฐฉ๋ฒ 1
function isMobile() {
return 'ontouchstart' in document.documentElement;
}
// ๋ฐฉ๋ฒ 2
function isMobile() {
try {
document.createEvent('TouchEvent');
return true;
} catch (e) {
return false;
}
}
์ฐธ๊ณ ๋ก in
์ฐ์ฐ์๋ ๋ช
์ํ ์์ฑ์ด ๊ฐ์ฒด์ ์กด์ฌํ๋์ง ์ฌ๋ถ๋ฅผ boolean ๊ฐ์ผ๋ก ๋ฐํํ๋ค.
const arr = [1, 2, 3, 4, 5];
0 in arr; // true (0๋ฒ index๊ฐ ์กด์ฌํ๋ฏ๋ก)
5 in arr; // false (5๋ฒ index๊ฐ ์กด์ฌํ์ง ์์ผ๋ฏ๋ก)
'length' in arr; // true (๋ฐฐ์ด์ length ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๋ฏ๋ก)
'concat' in arr; // true
const obj = { name: 'Smith', age: 30 };
'name' in obj; // true
'city' in obj; // false
window.matchMedia()
CSS๋ฅผ ํ์ฉํด ๋ชจ๋ฐ์ผ ์ฅ์น์ธ์ง ํ์ธํ๋ ๋ฐฉ๋ฒ. CSS๋ ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฅผ ํตํด ์น ํ์ด์ง์ ๋ฐ์ํ ์คํ์ผ์ ์ง์ ํ๋ค. ๋ง์ฝ ๋ชจ๋ฐ์ผ์ ๋์ํ ๋ฏธ๋์ด ์ฟผ๋ฆฌ ๊ตฌ๋ฌธ์ด ์ ํจํ๋ค๋ฉด, ํ์ฌ ์ฅ์น๋ ๋ชจ๋ฐ์ผ์ด๋ผ๊ณ ํ๋จํ ์ ์๋ค.
window.matchMedia()
๋ฉ์๋๋ CSS์ ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฌธ์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์, ํด๋น ๋ฌธ์ด ์ ํจํ์ง ํ๋จํ๋ค.
์๋ ์ฝ๋์์ window.matchMedia()
๋ฉ์๋๊ฐ ๋ฐ์ ํ๋ผ๋ฏธํฐ์ ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฌธ์ 760px์ ์ด๊ณผํ์ง ์๋ ์คํฌ๋ฆฐ์์๋ง ์ ํจํ๋ค. window.matchMedia()
๋ฉ์๋๊ฐ ๋ฐํํ๋ ๊ฐ์ฒด์ matches
์์ฑ์ boolean ๊ฐ์ ๋ฐํํ๋ค. true
๋ผ๋ฉด ๋ฏธ๋์ด ์กฐํ(media query)์ ์ฑ๊ณตํ๋ค๋ ๋ป์ด๊ณ , ๊ทธ๋ผ ์ ์ ์ ํ์ฌ ์ฅ์น๋ ๋ชจ๋ฐ์ผ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค.
let isMobile = window.matchMedia('only screen and (max-width: 760px)').matches;
์ฐธ๊ณ ๋ก ๋ฏธ๋์ด ์ฟผ๋ฆฌ์ only
์ฐ์ฐ์๋ ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฅผ ์ง์ํ๋ ์ฌ์ฉ์ ์์ด์ ํธ๋ง ๋ฏธ๋์ด ์ฟผ๋ฆฌ ๊ตฌ๋ฌธ์ ํด์ํ๋ผ๋ ๋ช
๋ น์ด๋ค. ์๋ตํ์ ๋ ๊ธฐ๋ณธ๊ฐ์ only
๋ก ์ฒ๋ฆฌํ๋ค. — ์ฐธ๊ณ
ํฌ์ธํฐ์ ์ ํ๋๋ก ํ๋จํ๋ ๋ฐฉ๋ฒ๋ ์๋ค. pointer:coarse
CSS ๊ตฌ๋ฌธ์ ํ์ฌ ์ฅ์น์ ํฌ์ธํฐ๊ฐ ์ ํํ์ง ์์์ ๋ํ๋ธ๋ค. ํด๋ํฐ์ ๋ง์ฐ์ค๋ฅผ ์ง์ํ์ง ์๊ณ ํฐ์น๋ง ์ง์ํ๋ฏ๋ก ์ด ์กฐ๊ฑด์ ๋ง์กฑํ๋ค.
let isMobile = window.matchMedia('(pointer:coarse)').matches;
์ผ๋ถ ์ฅ์น๋ ๋ง์ฐ์ค์ ํฐ์น ๊ฐ์ ์ฌ๋ฌ ํฌ์ธํฐ๋ฅผ ๋์์ ์ง์ํ๋ค. pointer:coarse
๋ ๋ฉ์ธ ํฌ์ธํฐ๋ฅผ ํ๋จํ๋ ๋ฐ๋ง ์ฌ์ฉ๋๋ค. ์ด๋ ๋ชจ๋ ํฌ์ธํฐ๋ฅผ ํ๋ณํ๋ any-pointer
๋ช
๋ น์ ์ฌ์ฉํ ์ ์๋ค. ๋ชจ๋ ํฌ์ธํฐ ์ค ํ๋์ ํฌ์ธํฐ๋ผ๋ ์ ํํ์ง ์์ผ๋ฉด ์ฟผ๋ฆฌ ์กฐ๊ฑด์ ์ถฉ์กฑํ๋ค.
let isMobile = window.matchMedia('(any-pointer:coarse)').matches;
react-device-detect ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ฉ
์ 5๊ฐ์ง ๋ฐฉ๋ฒ ์ธ์, ์ด๋ฏธ ๋ค๋ฅธ ์ฌ๋์ด ์์ฑํด๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์๋ค. React๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋ค์ํ ๊ธฐ๋ฅ๊ณผ ์ธ๋ถํ๋ ์ฅ์น ๊ฐ์ง๋ฅผ ์ง์ํ๋ react-device-detect ์ถ์ฒํ๋ค.
import { isMobile } from 'react-device-detect';
if (isMobile) {
// ํ์ฌ ์ฅ์น๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ
}
CSS ๋ฏธ๋์ด ์ฟผ๋ฆฌ
CSS min-width
max-width
์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํ๋ฉด ์คํฌ๋ฆฐ ํญ์ ๋ฐ๋ผ ์ํ๋ ์คํ์ผ์ ์ ์ฉํ ์ ์๋ค. ํ์ง๋ง ๊ธฐ๊ธฐ๋ง๋ค ํ๋ฉด ํฌ๊ธฐ๊ฐ ์ฒ์ฐจ๋ง๋ณ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ค ํญ์ ๊ธฐ์ค์ผ๋ก ์ผ์์ง ์ ๋งคํ๋ค. ๋์ pointer
hover
์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํด์ ๋ ํ๋์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ๋ฅผ ํ๋ณํ ์ ์๋ค. — ์ฐธ๊ณ ๊ธ 1 | ์ฐธ๊ณ ๊ธ 2
coarse๋ ๊ฑฐ์น(๋ฐ์์ด smooth), ๊ตต์(๋ฐ์์ด fine) ๋ฑ์ ๋ป์ ๊ฐ์ง ๋จ์ด
pointer ์ฟผ๋ฆฌ — ํฌ์ธํฐ ์ฅ์น ์ ๋ฌด ํ๋จ
- none : ํฌ์ธํฐ ์ฅ์น๊ฐ ์์ ๋
- coarse : ํฌ์ธํฐ ์ฅ์น๊ฐ ์์ง๋ง ์ ํ๋๊ฐ ๋์ง ์์ ๋(ํฐ์น์คํฌ๋ฆฐ, ํค๋ฅํธ ๋ฑ)
- fine : ์ ๋ฐ ํฌ์ธํฐ ์ฅ์น์ผ ๋(๋ง์ฐ์ค, ํฐ์นํจ๋ ๋ฑ)
hover ์ฟผ๋ฆฌ — hover ๊ฐ๋ฅ ์ฌ๋ถ ํ๋จ
- hover : ๊ธฐ๋ณธ ์ฅ์น๋ก ์ ํํ hover๋ฅผ ํ ์ ์์ ๋(๋ง์ฐ์ค, ํฐ์นํจ๋ ๋ฑ)
- none :
- ํฌ์ธํฐ ์ฅ์น๊ฐ ์์ ๋
- ํฌ์ธํฐ ์ฅ์น๊ฐ hover๋ฅผ ์ง์ํ์ง ์์ ๋
- ํธ๋ฒ ๊ฐ๋ฅํ ์ฅ์น๊ฐ ์์ผ๋ ๋กฑํญ(Long Tab) ๋์์ผ๋ก hover ํด์ผํ ๋(ํฐ์น์คํฌ๋ฆฐ ๋ฑ)
pointer, hover ๋ ์ฟผ๋ฆฌ๋ฅผ ๊ฒฐํฉํด์ ๋๋ฐ์ด์ค๋ฅผ ํ๋จํ๋ ์์
/* smartphones, touchscreens */
@media (hover: none) and (pointer: coarse) { }
/* stylus-based screens */
@media (hover: none) and (pointer: fine) { }
/* Nintendo Wii controller, Microsoft Kinect */
@media (hover: hover) and (pointer: coarse) { }
/* mouse, touch pad */
@media (hover: hover) and (pointer: fine) { }
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JS] ์๋ฐ์คํฌ๋ฆฝํธ Map / Set ์๋ฃ๊ตฌ์กฐ (0) | 2024.04.27 |
---|---|
[Web] ์ธ์ vs ์ฟ ํค vs ํ ํฐ (0) | 2024.04.27 |
[JS] ES Modules ๋ชจ๋ (Import / Export ์์คํ ) (0) | 2024.04.26 |
[Git] SSH ๊ณต๊ฐํค ๋ง๋ค๊ธฐ / Credential ์ธ์ฆ ์์คํ (0) | 2024.04.26 |
[HTML/CSS] focus-within โ ์์ ์์๊ฐ ํฌ์ปค์ค ๋์ ๋ ๋ถ๋ชจ ์คํ์ผ ์ง์ (0) | 2024.04.25 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[JS] ์๋ฐ์คํฌ๋ฆฝํธ Map / Set ์๋ฃ๊ตฌ์กฐ
[JS] ์๋ฐ์คํฌ๋ฆฝํธ Map / Set ์๋ฃ๊ตฌ์กฐ
2024.04.27 -
[Web] ์ธ์ vs ์ฟ ํค vs ํ ํฐ
[Web] ์ธ์ vs ์ฟ ํค vs ํ ํฐ
2024.04.27 -
[JS] ES Modules ๋ชจ๋ (Import / Export ์์คํ )
[JS] ES Modules ๋ชจ๋ (Import / Export ์์คํ )
2024.04.26 -
[Git] SSH ๊ณต๊ฐํค ๋ง๋ค๊ธฐ / Credential ์ธ์ฆ ์์คํ
[Git] SSH ๊ณต๊ฐํค ๋ง๋ค๊ธฐ / Credential ์ธ์ฆ ์์คํ
2024.04.26