Как определить сенсорный экран в JavaScript и CSS — и почему ontouchstart врёт

Самый популярный ответ на этот вопрос — 'ontouchstart' in window. Он ошибается в обе стороны.
На ноутбуке с сенсорным экраном он скажет «тач», хотя человек весь день работает мышкой. А на iPad Safari по умолчанию притворяется компьютером Mac: в его user agent написано Macintosh. Проверка по user agent скажет «десктоп» — и человек получит меню, которое открывается только наведением.
Хорошая новость: правильный способ короче неправильного. Разберём по шагам.
Шаг 1. Реши, что тебе на самом деле нужно
«Это тач-устройство?» — почти всегда не тот вопрос. На самом деле тебя волнует одно из двух:
- Умеет ли устройство наводить? Если нет — эффекты на
:hoverи всплывающие подсказки не сработают. - Насколько точный указатель? Палец — грубый, мышь — точная. Для пальца нужны кнопки крупнее.
Под каждый вопрос в браузере есть свой точный инструмент.
Шаг 2. Прячь hover-эффекты за проверкой в CSS
Вместо того чтобы угадывать тип устройства, спроси браузер напрямую:
/* эффект при наведении — только там, где наведение реально есть */
@media (hover: hover) and (pointer: fine) {
.card:hover {
transform: translateY(-4px);
}
}
hover: hover — основной указатель умеет наводить. pointer: fine — он точный, как мышь. На телефоне правило просто не включится. И больше не будет «залипшего» hover, который на мобильном срабатывает от касания и не уходит.
Если у тебя на hover держится что-то важное — например, подсказка, — разбор есть в статье почему подсказка не показывается на телефоне.
Есть и обратный приём: на устройствах без наведения покажи то, что обычно прячется под hover. Например, кнопки «редактировать» и «удалить» у карточки:
@media (hover: none) {
.card .actions { opacity: 1; }
}
На компьютере они появляются при наведении, а на телефоне видны всегда. Палец до них дотянется.
Шаг 3. Увеличь цели касания для пальца
@media (pointer: coarse) {
button, a.nav-link {
min-height: 44px;
min-width: 44px;
}
}
pointer: coarse — основной указатель грубый, то есть палец. 44 точки — минимальный размер кнопки из рекомендаций Apple для iPhone. Меньше — и человек промахивается.
Шаг 4. Если нужно в JavaScript — используй те же запросы
Те же условия доступны из кода через matchMedia:
const coarse = window.matchMedia("(pointer: coarse)");
if (coarse.matches) {
enableSwipeGallery();
}
coarse.addEventListener("change", (e) => {
// планшет подключили к клавиатуре с тачпадом — основной указатель сменился
e.matches ? enableSwipeGallery() : disableSwipeGallery();
});
Обрати внимание на change. Устройство может сменить основной указатель прямо во время работы: планшет пристегнули к клавиатуре с тачпадом. Проверка один раз при загрузке это пропустит.
Шаг 5. Нужно «есть ли тач вообще» — бери any-pointer
pointer и hover смотрят только на основной указатель. Если важно, есть ли хоть один сенсор среди всех, есть приставка any-:
const hasAnyTouch = window.matchMedia("(any-pointer: coarse)").matches;
На ноутбуке с сенсорным экраном: pointer: fine (главное — тачпад или мышь), но any-pointer: coarse (сенсор тоже есть). Вот это и есть честный ответ на исходный вопрос. Для iPad есть ещё navigator.maxTouchPoints > 0 — он вернёт число касаний, даже когда user agent притворяется Mac.
Шаг 6. Как именно нажали — смотри в событии
Иногда важно не «что за устройство», а «чем сделали это нажатие». Для этого есть Pointer Events:
button.addEventListener("pointerdown", (e) => {
console.log(e.pointerType); // "mouse", "touch" или "pen"
});
Одно событие на все три способа ввода. Не нужно вешать отдельно click и touchstart — и ловить двойные срабатывания.
Шаг 7. Проверь на живом устройстве
В Chrome DevTools открой режим устройства (Ctrl+Shift+M) и выбери телефон — он эмулирует касания. Но эмулятор не покажет настоящий размер пальца. Открой сайт с телефона в той же сети Wi-Fi и потыкай в кнопки сам.
Что получится
- На телефоне нет залипших hover-эффектов, кнопки удобного размера.
- На ноутбуке с сенсором интерфейс остаётся «мышиным», но не ломается от касаний.
- iPad получает мобильное поведение, хотя называет себя Mac.
Остальные детали мобильной вёрстки — в статье как сделать сайт удобным на телефоне.
Можно ли просто проверить ширину экрана?
Ширина говорит о размере, а не о способе ввода. Планшет в альбомной ориентации шире многих ноутбуков, а на узком окне десктопа есть мышь. Для раскладки бери ширину, для поведения — hover и pointer.
Работает ли это во всех браузерах?
Да, hover, pointer, any-pointer и Pointer Events поддерживают все современные браузеры, включая Safari на iPhone. Полифилы не нужны.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





