21

For my app, I need to radically change the entire UX for touch devices using an onscreen keyboard (eg. mobile, touch TV) vs mouse/kbd devices (eg. desktop, a mobile with a bluetooth mouse/kbd).

NB. I've already grokked responsive layout with CSS grid and media queries, so that aspect is dealt with. My issue isn't one of layout, it's that the entire UX needs to be fundamentally different. The best option I have so far is to listen for a mousemove on the whole viewport.

How can I do this using modern browsers?

Note I've already read the existing answers which are all several years old, and generally conclude that it can't be done.

pinoyyid
  • 21,499
  • 14
  • 64
  • 115
  • You might need to consider carefully what you mean by "touch device". There are quite a few desktops that support touch, and likely there will be more. Typically UIs are based on screen size, with touch support based on detection. Touch is related to user interaction and really is independent of screen size. – RobG May 27 '19 at 11:05
  • 1
    exactly. So it's not so much that I want to detect touch, as I want to detect the absence of mouse/keyboard. Screen size is relatively unimportant to my app, and where it does matter, I have that covered with grid/media queries. For my purposes, something like a flip laptop that supports touch/tablet mode, is a desktop. If there was a way to detect that the user has flipped it into tablet mode, that would be sweet. – pinoyyid May 27 '19 at 11:25
  • I found it useful for detecting touch devices https://stackoverflow.com/a/4819886/9161843 – Nafis Apr 17 '20 at 03:12

3 Answers3

34

This is really simple with just one line of code:

const touch = matchMedia('(hover: none)').matches;

- What? matchMedia?
- This is just a JS API to do CSS @media queries. And it is supported in modern browsers: https://caniuse.com/#feat=matchmedia. Of course, you may use such queries directly in CSS:

@media (hover: none){
    /* touch stuff goes here */
}

- Ok, what @media queries may be also useful?

@media (hover: none) and (pointer: coarse) {
    /* touchscreens */
}
@media (hover: none) and (pointer: fine) {
    /* stylus */
}
@media (hover: hover) and (pointer: coarse) {
    /* controllers */
}
@media (hover: hover) and (pointer: fine) {
    /* mouse or touchpad */
}

But this will query only the primary input method. If you want to go deeper, you may use any-hover and any-pointer to query all input devices.

UPD: hack for old browsers removed, seems like most old browsers does not support hover and pointer media queries too. You may use touch event detection and touch-only navigator properties from another answers

UPD2: In your case, it's preferable to use

const touch = matchMedia('(hover: none), (pointer: coarse)').matches;
4

You can detect using Javascript using a simple condition here

if(('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints > 0)) {
    //this is a touch device you can any action here 
}else {
    //it's not a touch device another code here
}

Also, the following link here https://ctrlq.org/code/19616-detect-touch-screen-javascript

Md. Abu Sayed
  • 2,396
  • 2
  • 18
  • 26
  • 3
    In case someone lands here in 2021 : it's navigator.maxTouchPoints and not navigator.MaxTouchPoints – Fab Mar 29 '21 at 15:45
2

In javascript.

 if ("ontouchstart" in document.documentElement)
    {
        document.write("your device is a touch screen device.");
    }
    else
    {
         document.write("your device is NOT a touch device");
    }

code pen

Thameem
  • 700
  • 1
  • 13
  • 38
  • How does this identify touch devices that have pointing and keyboard devices attached vs those that don't? That's what the OP is asking. – RobG May 27 '19 at 12:28