5 надежных способов определить устройство пользователя на JavaScript

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Фронтенд-разработчики
  • Специалисты по веб-разработке
  • Студенты и ученики курсов по программированию и веб-разработке

    Каждый фронтенд-разработчик рано или поздно сталкивается с необходимостью адаптировать пользовательский опыт под разные устройства. Смартфоны, планшеты, десктопы — все они требуют особого подхода. Однако одних только media queries порой недостаточно. Вам может понадобиться программное определение устройства, чтобы управлять логикой вашего приложения, оптимизировать производительность или предлагать пользователям разный функционал. Я подготовил 5 проверенных методов с готовыми фрагментами кода, которые можно внедрить в проект прямо сейчас. 💡

Хотите углубить свои знания в веб-разработке? На курсе Обучение веб-разработке от Skypro вы освоите не только базовые методы определения устройств пользователя, но и продвинутые техники адаптивной разработки. Наши выпускники создают интерфейсы, которые одинаково хорошо работают на всех устройствах. Курс включает реальные проекты с использованием JavaScript и современных фреймворков!

Зачем и когда нужно определять устройство пользователя

Определение устройства пользователя — это не прихоть, а необходимость в ряде сценариев. Несмотря на популярность подхода "mobile first" и адаптивного дизайна, программное определение устройства остаётся мощным инструментом для оптимизации пользовательского опыта. 📱💻

Михаил, ведущий фронтенд-разработчик

Недавно мы запускали финтех-приложение, где требовалось предлагать разный функционал для пользователей разных устройств. Мобильным пользователям мы давали доступ к упрощённой версии калькулятора кредитов, а десктопным — полную версию с расширенными опциями. Сначала мы пытались определять устройство только по ширине экрана через media queries, но столкнулись с ограничениями: пользователи десктопов с маленьким окном браузера получали мобильную версию.

После внедрения JavaScript-определения устройств на основе комбинации факторов (User-Agent + сенсорные возможности) точность определения выросла до 98%. Это привело к увеличению среднего времени сессии на 27% — пользователи получали именно тот интерфейс, который оптимален для их устройства.

Вот основные случаи, когда программное определение устройства жизненно необходимо:

  • Оптимизация производительности — загрузка только тех ресурсов, которые нужны для конкретного устройства
  • Разная бизнес-логика — некоторые функции могут быть доступны только на определённых устройствах
  • Специфичный UX — создание разных пользовательских сценариев для мобильных и десктопных пользователей
  • Аналитика и метрики — сбор данных о том, какими устройствами пользуются ваши клиенты
  • Тестирование — запуск определённых тестов только на целевых устройствах
Задача Подходящие методы детекции Приоритет
Адаптивный дизайн CSS Media Queries (без JS) Высокий
Разная логика приложения Feature Detection + User-Agent Высокий
Оптимизация ресурсов Серверная детекция Средний
Сбор аналитики User-Agent + библиотеки Низкий

Теперь рассмотрим конкретные методы определения устройства пользователя и их практическую реализацию.

Пошаговый план для смены профессии

Метод №1: Анализ User-Agent строки для определения устройств

Самый базовый и распространённый способ — парсинг строки User-Agent из заголовка HTTP-запроса. В JavaScript это можно сделать через свойство navigator.userAgent. Этот метод имеет давнюю историю и все ещё широко используется, несмотря на определённые недостатки. 🔍

Вот простой пример кода для определения типа устройства:

JS
Скопировать код
function detectDevice() {
const userAgent = navigator.userAgent.toLowerCase();

const isMobile = /iphone|ipad|ipod|android|blackberry|windows phone/g.test(userAgent);
const isTablet = /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/g.test(userAgent);

if (isTablet) return 'tablet';
if (isMobile) return 'mobile';
return 'desktop';
}

console.log(`Вы используете: ${detectDevice()}`);

Преимущества этого метода:

  • Простота реализации — всего несколько строк кода
  • Работает без дополнительных библиотек — нет внешних зависимостей
  • Доступен на всех браузерах — высокая совместимость

Однако у этого подхода есть существенные недостатки:

  • Ненадёжность — строки User-Agent могут быть подделаны или изменены
  • Сложность поддержки — с появлением новых устройств регулярные выражения нужно обновлять
  • Проблемы с точностью — некоторые устройства сложно однозначно классифицировать
  • Устаревание — браузеры постепенно ограничивают информативность User-Agent

Александр, технический директор

Мы развиваем продукт с аудиторией более 2 миллионов пользователей. Изначально для определения устройств использовали только User-Agent. Это казалось надёжным решением, пока мы не заметили странные аномалии в аналитике — около 15% пользователей определялись некорректно.

После расследования выяснилось, что многие браузеры (особенно мобильные версии Chrome и Safari) стали "замораживать" или обобщать User-Agent строки, чтобы защитить пользователей от фингерпринтинга. Мы перешли на комбинированный подход: User-Agent + определение через функциональные возможности. Это повысило точность определения до 97% и позволило правильно настраивать интерфейс для всех пользователей.

Метод №2: Использование navigator.userAgent с готовыми библиотеками

Ручное создание регулярных выражений для всех возможных устройств — утомительная задача с высокими шансами на ошибку. Гораздо эффективнее использовать проверенные библиотеки, которые постоянно обновляются и учитывают нюансы разных устройств и браузеров. 📚

Наиболее популярные библиотеки для определения устройств:

Название библиотеки Размер (min+gzip) Точность определения Активная поддержка
device.js ~1KB Средняя Умеренная
mobile-detect.js ~14KB Высокая Активная
UAParser.js ~5KB Высокая Активная
Bowser ~4KB Высокая Умеренная

Пример использования популярной библиотеки UAParser.js:

JS
Скопировать код
// Подключение через CDN
// <script src="https://cdnjs.cloudflare.com/ajax/libs/UAParser.js/0.7.24/ua-parser.min.js"></script>

// Или через npm
// npm install ua-parser-js

const parser = new UAParser();
const result = parser.getResult();

console.log('Устройство:', result.device.type || 'desktop');
console.log('Операционная система:', result.os.name, result.os.version);
console.log('Браузер:', result.browser.name, result.browser.version);

// Более детальное определение
function getDeviceType() {
const device = result.device.type;
if (device === 'mobile') return 'Смартфон';
if (device === 'tablet') return 'Планшет';
if (device === 'smarttv') return 'Smart TV';
if (device === 'console') return 'Игровая консоль';
return 'Компьютер';
}

console.log('Тип устройства:', getDeviceType());

Преимущества использования готовых библиотек:

  • Высокая точность — команды разработчиков библиотек следят за обновлениями и новыми устройствами
  • Дополнительная информация — помимо типа устройства можно получить данные о браузере, ОС и прочем
  • Минимизация ошибок — код проверен тысячами разработчиков
  • Экономия времени — не нужно писать и поддерживать собственный парсер

Несмотря на все преимущества, этот метод всё ещё опирается на User-Agent, что означает наследование некоторых его недостатков. Для более надёжных решений стоит комбинировать библиотеки с другими методами определения.

Метод №3: Определение устройства через размер окна и сенсорные возможности

Третий подход базируется на анализе технических возможностей устройства и размеров экрана. Этот метод позволяет определить не только категорию устройства, но и его ориентацию (портретная/альбомная), что часто необходимо для корректной адаптации интерфейса. 📏👆

Пример кода для определения устройства по размеру экрана и сенсорным возможностям:

JS
Скопировать код
function detectDeviceByCapabilities() {
// Определяем наличие сенсорного экрана
const hasTouchScreen = (('ontouchstart' in window) || 
(navigator.maxTouchPoints > 0) || 
(navigator.msMaxTouchPoints > 0));

// Получаем размер окна браузера
const width = window.innerWidth;

// Логика определения типа устройства
if (hasTouchScreen) {
if (width < 768) {
return 'mobile';
} else if (width < 1024) {
return 'tablet';
} else {
return 'touch desktop'; // Например, Surface Pro
}
} else {
return 'desktop';
}
}

// Проверка при изменении размера окна
window.addEventListener('resize', function() {
console.log('Текущее устройство:', detectDeviceByCapabilities());
});

console.log('Начальное определение устройства:', detectDeviceByCapabilities());

Этот метод также может отслеживать изменения ориентации экрана, что полезно для мобильных устройств:

JS
Скопировать код
// Определение ориентации устройства
function getOrientation() {
return window.innerWidth > window.innerHeight ? 'landscape' : 'portrait';
}

// Прослушивание изменения ориентации
window.addEventListener('resize', function() {
console.log('Текущая ориентация:', getOrientation());
});

// Можно комбинировать с предыдущим методом
window.addEventListener('resize', function() {
console.log(`${detectDeviceByCapabilities()} в ${getOrientation()} режиме`);
});

Основные преимущества этого подхода:

  • Реальные характеристики — определение основано на фактических параметрах устройства, а не строках
  • Динамическая адаптация — можно реагировать на изменение размера окна или ориентации
  • Меньшая зависимость от User-Agent — работает даже в случаях, когда User-Agent не предоставляет достоверной информации

Недостатки метода:

  • Сложность точной классификации — планшет с маленьким экраном может быть принят за мобильное устройство
  • Пограничные случаи — устройства на границе категорий могут определяться по-разному
  • Ресурсоёмкость — постоянное отслеживание изменений размеров может влиять на производительность

Метод №4: Feature detection вместо device detection

Вместо того чтобы сосредоточиться на определении типа устройства, во многих случаях эффективнее определять конкретные возможности браузера или устройства. Этот подход называется "определение функций" (feature detection) и является более гибким и устойчивым к изменениям. 🧩

Feature detection фокусируется на вопросе "что может устройство?", а не "что это за устройство?". Это позволяет создавать более устойчивые и гибкие приложения.

JS
Скопировать код
// Проверка наличия сенсорного ввода
function hasTouchCapability() {
return 'ontouchstart' in window || 
navigator.maxTouchPoints > 0 || 
navigator.msMaxTouchPoints > 0;
}

// Проверка поддержки определённых API
function checkDeviceCapabilities() {
const capabilities = {
touch: hasTouchCapability(),
geolocation: 'geolocation' in navigator,
webGL: (function() {
try {
const canvas = document.createElement('canvas');
return !!(window.WebGLRenderingContext && 
(canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
} catch(e) {
return false;
}
})(),
deviceMotion: 'DeviceMotionEvent' in window,
deviceOrientation: 'DeviceOrientationEvent' in window,
ambientLight: 'AmbientLightSensor' in window,
batteryAPI: 'getBattery' in navigator,
screenOrientation: screen.orientation ? true : false
};

return capabilities;
}

const deviceCaps = checkDeviceCapabilities();
console.log('Возможности устройства:', deviceCaps);

// Использование этой информации для адаптации интерфейса
if (deviceCaps.touch) {
console.log('Включаем интерфейс для сенсорных устройств');
// enableTouchInterface();
}

if (deviceCaps.deviceMotion) {
console.log('Это устройство поддерживает определение движения');
// enableMotionFeatures();
}

На основе определённых функций можно сделать предположение о типе устройства:

JS
Скопировать код
function guessDeviceType() {
const caps = checkDeviceCapabilities();

// Мобильные устройства обычно имеют сенсор движения и ориентации
if (caps.touch && (caps.deviceMotion || caps.deviceOrientation)) {
return window.innerWidth < 768 ? 'smartphone' : 'tablet';
}

// Планшеты обычно сенсорные, но не всегда имеют датчики движения
if (caps.touch && !caps.deviceMotion) {
return 'tablet or touch-desktop';
}

// Десктопы редко имеют сенсорный экран
if (!caps.touch) {
return 'desktop';
}

return 'unknown';
}

console.log('Предполагаемый тип устройства:', guessDeviceType());

Основные преимущества feature detection:

  • Ориентация на возможности, а не типы — адаптация под реальные характеристики устройства
  • Будущая совместимость — код не нужно обновлять при появлении новых устройств
  • Прогрессивное улучшение — можно плавно деградировать функционал при отсутствии возможностей
  • Более надёжные решения — нет ложных предположений на основе типа устройства

Этот подход становится особенно актуальным с появлением гибридных устройств (ноутбуки с сенсорными экранами, планшеты с клавиатурами), которые сложно однозначно отнести к определённой категории.

Метод №5: Серверная и клиентская детекция: комбинированный подход

Наиболее комплексное и надёжное решение — комбинирование серверной и клиентской детекции устройств. Этот подход устраняет недостатки отдельных методов и повышает точность определения, обеспечивая оптимальную производительность. 🔄

Схема работы комбинированного подхода:

  1. Первичное определение на сервере — анализ User-Agent при первом запросе
  2. Отправка адаптированных ресурсов — сервер отправляет только те ресурсы, которые необходимы для предполагаемого устройства
  3. Уточнение на стороне клиента — JavaScript проверяет реальные характеристики устройства
  4. Корректировка интерфейса — при необходимости происходит динамическая корректировка
  5. Сохранение данных — информация о правильном определении сохраняется для будущих запросов

Пример серверной части (Node.js с Express):

JS
Скопировать код
// Серверная детекция с использованием express и mobile-detect
const express = require('express');
const MobileDetect = require('mobile-detect');

const app = express();

app.use((req, res, next) => {
const userAgent = req.headers['user-agent'];
const md = new MobileDetect(userAgent);

// Определяем тип устройства
if (md.mobile() && !md.tablet()) {
req.deviceType = 'mobile';
} else if (md.tablet()) {
req.deviceType = 'tablet';
} else {
req.deviceType = 'desktop';
}

// Добавляем информацию в локальные переменные для шаблонов
res.locals.deviceType = req.deviceType;

next();
});

app.get('/', (req, res) => {
// Используем информацию о устройстве для отправки разного контента
switch(req.deviceType) {
case 'mobile':
res.render('mobile-index', { title: 'Мобильная версия' });
break;
case 'tablet':
res.render('tablet-index', { title: 'Версия для планшета' });
break;
default:
res.render('desktop-index', { title: 'Полная версия' });
}
});

app.listen(3000, () => {
console.log('Сервер запущен на порту 3000');
});

Клиентская часть для уточнения и корректировки:

JS
Скопировать код
// Получаем первичное определение от сервера
const serverDetectedDevice = document.documentElement.getAttribute('data-device-type');

// Проверяем корректность определения
function verifyDeviceType() {
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
const screenWidth = window.innerWidth;

let actualDeviceType;

if (isTouchDevice) {
if (screenWidth < 768) {
actualDeviceType = 'mobile';
} else if (screenWidth < 1024) {
actualDeviceType = 'tablet';
} else {
actualDeviceType = 'touch-desktop';
}
} else {
actualDeviceType = 'desktop';
}

// Если серверное определение неверно
if (serverDetectedDevice !== actualDeviceType) {
console.log(`Корректировка: сервер определил ${serverDetectedDevice}, фактически ${actualDeviceType}`);

// Отправляем правильные данные на сервер для будущих запросов
fetch('/api/update-device-type', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ 
detectedType: actualDeviceType,
userAgent: navigator.userAgent
})
});

// Корректируем UI если нужно
adjustInterface(actualDeviceType);
}

return actualDeviceType;
}

function adjustInterface(deviceType) {
// Корректируем интерфейс на основе реального типа устройства
if (deviceType === 'mobile') {
// Загружаем дополнительные мобильные компоненты если нужно
loadMobileSpecificResources();
} else if (deviceType === 'tablet') {
// Адаптируем для планшета
adjustTabletLayout();
}
}

// Запускаем проверку после загрузки страницы
document.addEventListener('DOMContentLoaded', verifyDeviceType);

Преимущества комбинированного подхода:

  • Максимальная точность — ошибки одного метода компенсируются другим
  • Оптимизация ресурсов — сервер изначально отправляет только необходимые файлы
  • Самообучение — система может накапливать данные для улучшения первичного определения
  • Гибридные устройства — эффективное определение даже для устройств, которые сложно классифицировать

Этот метод требует больше усилий для реализации, но обеспечивает наилучший баланс между производительностью и точностью определения устройств пользователей.

Выбор метода определения устройства зависит от конкретных потребностей вашего проекта. Для большинства современных веб-приложений оптимальным решением будет комбинация feature detection с элементами серверной предварительной оптимизации. Вместо жёсткой классификации устройств сосредоточьтесь на их возможностях — создавайте интерфейсы, которые адаптируются к любым условиям использования. Такой подход обеспечит долговечность вашего кода и наилучший опыт для пользователей независимо от того, какие устройства появятся в будущем.

Загрузка...