Как определить тип устройства в 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 рекомендуется комбинировать несколько методов и обрабатывать крайние случаи.

Определение устройств в JavaScript - comments

En
Device js (javascript)