Как определить тип устройства в JavaScript: обзор техник
Определение устройств в JavaScript
При разработке веб-приложений часто требуется узнать, с какого устройства пользователь заходит на сайт: компьютер, планшет или смартфон. В JavaScript существует несколько подходов для решения этой задачи. Ниже рассмотрены основные методы и их особенности.
Как определить мобильное устройство по размеру экрана и типу указателя?
Наиболее эффективный способ - использовать window.matchMedia в сочетании с проверкой типа ввода. Это позволяет адаптироваться к реальным возможностям устройства, а не полагаться только на строку user-agent.
// Проверка ширины экрана и наличия грубого указателя (палец)
const isMobile = window.matchMedia('(max-width: 768px) and (pointer: coarse)').matches;
if (isMobile) {
console.log('Устройство скорее всего смартфон или планшет');
} else {
console.log('Десктоп или устройство с точным указателем');
}
Device js (определение устройств в javascript)
Пояснение: медиа-выражение pointer: coarse указывает на наличие сенсорного экрана, а максимальная ширина 768px покрывает большинство смартфонов и небольших планшетов. Такой подход не требует парсинга строк и работает быстро.
Проблема: Медиа-запросы не всегда точно определяют тип устройства. Например, на десктопе с окном браузера малой ширины условие может сработать ложно.
Решение: Дополнительно проверять наличие сенсорной поддержки через ('ontouchstart' in window) или navigator.maxTouchPoints > 0.
Как узнать устройство через строку user-agent?
Классический метод - парсинг navigator.userAgent. С помощью регулярных выражений можно определить браузер, ОС и факт мобильности.
function isMobileByUA() {
const ua = navigator.userAgent.toLowerCase();
return /mobile|android|iphone|ipad|phone|blackberry|iemobile|opera mini/.test(ua);
}
console.log('Мобильное?', isMobileByUA());
Javascript разработка (разработка на javascript)
Пояснение: Регулярное выражение перебирает ключевые слова, характерные для мобильных устройств. Недостаток - строка user-agent может быть подделана или содержать устаревшие данные.
Проблема: Многие браузеры (особенно на десктопе) могут включать слово "mobile" в user-agent (например, некоторые версии Chrome). Это приводит к ложным срабатываниям.
Решение: Дополнительно исключать десктопные браузеры, проверяя наличие !/windows|macintosh|linux/.test(ua).
Как определить устройство по наличию touch-событий?
Сенсорные экраны поддерживают события касания. Проверка на ontouchstart в окне - простой индикатор.
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
console.log('Поддержка касаний:', isTouchDevice);
файл javascript (файлы javascript)
Пояснение: Если хотя бы одно из условий истинно, значит устройство поддерживает сенсорный ввод. Однако на ноутбуках с сенсорным экраном и на гибридных устройствах эта проверка вернёт true, что не всегда подходит.
Проблема: Устройства с сенсорным экраном, но работающие в десктопной ориентации (например, планшет с клавиатурой), могут некорректно классифицироваться как планшеты.
Решение: Комбинировать проверку с шириной экрана или с ориентацией - window.matchMedia('(orientation: portrait)').matches.
Как использовать библиотеку ua-parser-js для определения устройства?
Библиотека ua-parser-js предоставляет удобный API для извлечения информации о браузере, ОС и устройстве из user-agent.
// Подключение библиотеки (CDN)
// <script src="https://cdn.jsdelivr.net/npm/ua-parser-js@2.0.0/dist/ua-parser.min.js"></script>
const parser = new UAParser();
const result = parser.getResult();
console.log('Тип устройства:', result.device.type); // "mobile", "tablet", "console" и т.д.
console.log('Модель:', result.device.model);
Пояснение: Библиотека парсит user-agent и возвращает структурированные данные. Поле device.type может быть "mobile", "tablet", "desktop" и др. Это удобно, но добавляет зависимость от внешнего кода.
Проблема: Библиотека может устареть - новые устройства или браузеры могут не распознаваться корректно.
Решение: Регулярно обновлять библиотеку до актуальной версии и предусмотреть запасные проверки.
Как определить планшет отдельно от смартфона?
Иногда требуется различать планшеты и телефоны. Для этого можно комбинировать ширину экрана и user-agent.
function getDeviceCategory() {
const width = window.innerWidth;
const ua = navigator.userAgent.toLowerCase();
const isTablet = /tablet|ipad|playbook|silk|android(?!.*mobile)/.test(ua);
const isPhone = /mobile|iphone|android.*mobile/.test(ua);
if (isTablet) return 'tablet';
if (isPhone) return 'phone';
if (width >= 1024) return 'desktop';
return 'unknown';
}
console.log('Категория:', getDeviceCategory());
Пояснение: Регулярные выражения учитывают, что в user-agent планшетов часто отсутствует слово "mobile" при наличии "android". Дополнительная проверка ширины помогает уточнить категорию.
Проблема: На устройствах-трансформерах (например, Microsoft Surface) user-agent может быть похож на десктопный, а ширина меняется при переключении режимов.
Решение: Слушать событие изменения размера экрана (resize) и обновлять категорию динамически.
Выбор метода зависит от требуемой точности, производительности и контекста использования. Для простых адаптивных интерфейсов достаточно matchMedia, для более точного определения - комбинация с парсингом user-agent или готовые библиотеки.
Расширенные примеры и нестандартные сценарии определения устройств в JavaScript.
Пример 1: Определение устройства на сервере (Node.js) с помощью библиотеки device-detector-js
// Установка: npm install device-detector-js
const DeviceDetector = require('device-detector-js');
const deviceDetector = new DeviceDetector();
const userAgent = 'Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
const result = deviceDetector.parse(userAgent);
console.log('Тип устройства:', result.device?.type); // "smartphone"
console.log('Бренд:', result.device?.brand); // "Samsung"
console.log('Модель:', result.device?.model); // "Galaxy S21"
Тип устройства: smartphone Бренд: Samsung Модель: Galaxy S21
Пример 2: Динамическое переключение между мобильной и десктопной версиями с использованием matchMedia и слушателя событий
const mobileMediaQuery = window.matchMedia('(max-width: 767px)');
function handleLayoutChange(e) {
if (e.matches) {
console.log('Мобильное представление (ширина <= 767px)');
// Здесь можно подгрузить мобильные стили или скрипты
} else {
console.log('Десктопное представление (ширина > 767px)');
}
}
mobileMediaQuery.addEventListener('change', handleLayoutChange);
// Первоначальная проверка
handleLayoutChange(mobileMediaQuery);
Мобильное представление (ширина <= 767px)
Пример 3: Определение ориентации экрана и типа устройства для адаптации интерфейса
function detectOrientationAndDevice() {
const orientation = screen.orientation?.type || (window.innerHeight > window.innerWidth ? 'portrait' : 'landscape');
const isTouch = ('ontouchstart' in window) && window.matchMedia('(pointer: coarse)').matches;
const isMobile = window.matchMedia('(max-width: 480px)').matches;
let deviceType = 'desktop';
if (isTouch && isMobile) deviceType = 'phone';
else if (isTouch && !isMobile) deviceType = 'tablet';
console.log(`Ориентация: ${orientation}, Устройство: ${deviceType}`);
}
detectOrientationAndDevice();
Ориентация: portrait, Устройство: phone
Пример 4: Использование Modernizr для проверки поддержки определённых возможностей (touch, pointer)
// Modernizr подключается глобально
if (Modernizr.touchevents) {
console.log('Сенсорные события поддерживаются');
} else {
console.log('Сенсорные события отсутствуют');
}
if (Modernizr.pointerevents) {
console.log('Pointer Events доступны');
}
Сенсорные события поддерживаются Pointer Events доступны
Пример 5: Расширенный парсинг user-agent с использованием нескольких регулярных выражений для извлечения ОС и браузера
function parseUserAgent(ua) {
const uaLower = ua.toLowerCase();
const os = (() => {
if (/windows phone/.test(uaLower)) return 'Windows Phone';
if (/android/.test(uaLower)) return 'Android';
if (/iphone|ipad|ipod/.test(uaLower)) return 'iOS';
if (/macintosh|mac os x/.test(uaLower)) return 'macOS';
if (/windows/.test(uaLower)) return 'Windows';
if (/linux/.test(uaLower)) return 'Linux';
return 'Unknown';
})();
const browser = (() => {
if (/edge/.test(uaLower)) return 'Edge';
if (/opr|opera/.test(uaLower)) return 'Opera';
if (/chrome/.test(uaLower)) return 'Chrome';
if (/safari/.test(uaLower)) return 'Safari';
if (/firefox/.test(uaLower)) return 'Firefox';
return 'Unknown';
})();
const isMobile = /mobile|tablet|iemobile|touch/.test(uaLower);
return { os, browser, isMobile };
}
const info = parseUserAgent(navigator.userAgent);
console.log('ОС:', info.os);
console.log('Браузер:', info.browser);
console.log('Мобильное:', info.isMobile);
ОС: Android Браузер: Chrome Мобильное: true
Пример 6: Определение устройства по размеру экрана и плотности пикселей (Retina)
const dpr = window.devicePixelRatio || 1;
const smallScreen = window.innerWidth < 768;
const isRetina = dpr >= 2;
let device = 'desktop';
if (smallScreen && isRetina) {
device = 'phone (Retina)';
} else if (smallScreen) {
device = 'phone (standard)';
} else if (isRetina) {
device = 'tablet/desktop (Retina)';
}
console.log('Устройство:', device);
Устройство: phone (Retina)
Пример 7: Использование navigator.platform (устаревшее, но иногда полезное)
const platform = navigator.platform.toLowerCase();
let deviceType = 'unknown';
if (platform.includes('win') || platform.includes('mac') || platform.includes('linux')) {
deviceType = 'desktop';
} else if (platform.includes('ipad') || platform.includes('tablet')) {
deviceType = 'tablet';
} else if (platform.includes('iphone') || platform.includes('android')) {
deviceType = 'phone';
}
console.log('Тип (платформа):', deviceType);
Тип (платформа): desktop
Эти примеры охватывают как серверные, так и клиентские подходы, включая использование событий, определения ориентации, плотности пикселей и устаревших свойств. Для production рекомендуется комбинировать несколько методов и обрабатывать крайние случаи.