В JavaScript можно определить, является ли текущее устройство мобильным, несколькими способами. Рассмотрим наиболее распространённые методы.
Анализ строки User Agent браузера, который можно получить с помощью свойства navigator.userAgent, может дать приблизительную информацию об устройстве. Например, возьмем следующий код:
function isMobileDevice() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
if (isMobileDevice()) {
console.log("Это мобильное устройство");
} else {
console.log("Это не мобильное устройство");
}
В данном случае тестируем строку navigator.userAgent на наличие в ней распространенных маркеров мобильных устройств. Тем не менее этот способ имеет недостатки. В частности, строку с User Agent можно подделать. Также некоторые планшеты могут определяться как мобильные или наоборот.
Другой способ представляет проверку поддержки сенсора на текущем устройстве. В частности, мы можем проверять, поддерживает ли браузер сенсорные события (касания), что характерно для мобильных устройств и тачскринов. Для этого можно использовать проверку:
"ontouchstart" in window
Она проверяет, существует ли в объекте window свойство ontouchstart. Если да, значит, браузер поддерживает touch-события (например, на смартфонах и планшетах). Но важно помнить, что
некоторые десктопные браузеры (например, Chrome с эмуляцией) тоже могут возвращать true.
Более современный способ предполагает проверку свойства maxTouchPoints интерфейса Navigator (свойство navigator.maxTouchPoints), которое возвращает максимальное количество одновременных точек касания, поддерживаемых текущим устройством.
Если это свойство возвращает значение больше 0, значит, устройство сенсорное.
В конечном счете, мы можем совместить оба выше описанных способа проверки. На десктопах (без тачскрина) оба способа обычно дают false. На мобильных устройствах — true.
Но есть нюансы: некоторые ноутбуки с тачскрином (например, Windows Surface) вернут true. Браузеры в режиме эмуляции мобильных устройств тоже могут вернуть true.
function isMobile() {
return isTouchScreen = "ontouchstart" in window || navigator.maxTouchPoints > 0;
}
if (isMobile()) {
console.log("Мобильное устройство (сенсорный экран + малый размер)");
} else {
console.log("Десктоп или планшет");
}
Можно комбинировать проверку ширины экрана и поддержку сенсорных событий. Например:
function isMobile() {
const isTouchScreen = "ontouchstart" in window || navigator.maxTouchPoints > 0;
const isSmallScreen = window.innerWidth < 768; // Обычно мобильные устройства имеют ширину меньше 768px, но это не точно
return isTouchScreen && isSmallScreen;
}
if (isMobile()) {
console.log("Мобильное устройство (сенсорный экран + малый размер)");
} else {
console.log("Десктоп или планшет");
}
Из плюсов - это более точный метод, чем просто проверка User Agent. Однако на десктопах с сенсорными экранами может давать ложные срабатывания.
Можно использовать медиа-запросы для проверки мобильного разрешения с помощью метода window.matchMedia().
Этот метод возвращает объект MediaQueryList, который затем можно использовать для определения соответствия веб-страницы строке медиа-запроса, а также для мониторинга
соответствия страницы (или прекращения соответствия) этому медиа-запросу. Например:
function isMobileView() {
return window.matchMedia("(max-width: 767px)").matches;
}
if (isMobileView()) {
console.log("Мобильное разрешение экрана");
} else {
console.log("Широкий экран (десктоп/планшет)");
}
Из недостатков: этот способ не различает мобильные устройства и просто узкие окна браузера.
Плотность пикселей, которая представлена свойством window.devicePixelRatio, показывает соотношение между физическими и логическими пикселями на экране или DPR.
DPR = Физические пиксели/Логические (CSS) пиксели
Несколько примеров:
1.0 — обычный экран (старые ноутбуки, десктопы).
1.5-2.0 — HD-экраны (многие смартфоны, планшеты).
2.0-3.0+ — Retina (iPhone), Super AMOLED (Samsung).
Это значение полезно для:
Различения Retina-экранов (Apple) и высокоплотных дисплеев (Android).
Определения, является ли устройство смартфоном или планшетом (у смоартфонов обычно значение devicePixelRatio >= 2, а у десктопов — 1 или 1.25).
Оптимизации отображения графики (например, загрузка изображений в высоком разрешении для Retina-экранов).
Например, используем devicePixelRatio для определения устройства:
function isHighDensityDisplay() {
return window.devicePixelRatio >= 2;
}
if (isHighDensityDisplay()) {
console.log("Устройство с высоким DPI (скорее всего, мобильное)");
} else {
console.log("Обычный экран (возможно, десктоп)");
}
У iPhone (особенно Retina) значение DPR обычно 2 или 3, а у Android-устройств может быть 2.5, 3.5 и выше:
const dpr = window.devicePixelRatio;
if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
console.log(`Apple устройство с DPR = ${dpr}`);
} else if (/Android/i.test(navigator.userAgent)) {
console.log(`Android устройство с DPR = ${dpr}`);
} else {
console.log("Другое устройство (десктоп?)");
}
Благодаря этому мы можем оптимизировать различные аспекты, например, изображения под дисплеи Retina:
const dpr = window.devicePixelRatio;
const img = document.querySelector("img");
if (dpr >= 2) {
img.src = "image@2x.png"; // Загрузка HD-версии
} else {
img.src = "image.png"; // Обычная версия
}
Для оптимальной точности лучше всего использовать несколько проверок:
function isMobile() {
const userAgent = navigator.userAgent;
const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
const isSmallScreen = window.innerWidth < 768;
return isMobileUA || (isTouchDevice && isSmallScreen); // здесь возможны варианты типа (isMobileUA && isTouchDevice && isSmallScreen)
}
if (isMobile()) {
console.log("Мобильное устройство");
} else {
console.log("Десктоп или планшет");
}
Также можно объединить с DRP:
function isMobileDevice() {
const isMobileUA = /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
const isHighDPI = window.devicePixelRatio >= 2;
const isSmallScreen = window.innerWidth < 768;
return isMobileUA || (isHighDPI && isSmallScreen);
}
if (isMobileDevice()) {
console.log("Скорее всего, это мобильное устройство");
} else {
console.log("Десктоп или устройство без высокого DPI");
}
Или просто комбинировать отдельные аспекты, например, плотность пикселей и строку User Agent:
function isRetinaMobile() {
const dpr = window.devicePixelRatio;
const isApple = /iPhone|iPad|iPod/i.test(navigator.userAgent);
const isAndroid = /Android/i.test(navigator.userAgent);
return (dpr >= 2) && (isApple || isAndroid);
}