21

Today (or very recently) Chrome Beta updated to 17 for me and with it i noticed some funkiness in my web app. I noticed it was because a class was being added to the body element that normally only gets put there if there is touch event support which I check like this:

  try {  
    document.createEvent("TouchEvent");
    _device.touch = true;
  } catch (e) {
    _device.touch = false;
  }

And sure enough, i can create and trigger touch events on Chrome 17. First idea i had was, oh, i can check for touch, and see if a mouse click fails, therefore, there's a mouse, but MouseEvents trigger too.

How else can I check, without user agent sniffing, that it's an actual, touchable, device, and not just a browser that supports touch events.

Oscar Godson
  • 31,662
  • 41
  • 121
  • 201
  • What does it matter if the browser supports touch, if the computer doesn't? Just enable both touch and mouse events and let the user choose. – Blazemonger Jan 06 '12 at 20:29
  • This may help you: http://stackoverflow.com/questions/2915833/how-to-check-browser-for-touchstart-support-using-js-jquery – sransara Jan 06 '12 at 20:29
  • @mblase75 exactly what im looking for. Obv. touch devices are going to become more popular. – Oscar Godson Jan 06 '12 at 20:30
  • Unfortunately, checking for touch is now backwards because desk/laptops do/will support it. Try checking for mouse instead - but doing so with simulated events is tough. I solved that, see http://stackoverflow.com/a/15415643/342275. – marknadal Mar 14 '13 at 17:08
  • @marknadal The accepted answer below has been working on Yammer.com since I posted this a year ago :) – Oscar Godson Mar 15 '13 at 20:47
  • Fantastic work at Yammer, btw. I guess my comment related more to the description than the question title - and thus don't quite apply (thus the other thread). I still needed a way to detect if the device is primarily a touch device - not whether the browser supports touch events. The reverse-logic is that if a device is intended for touch use, it will only have touch and maybe a keyboard (but never a mouse). However if there is a mouse (but also touch), then touch is supplemental - as the mouse would only exist if the device design results in arm fatigue from touch, such as on a laptop. – marknadal Mar 18 '13 at 13:18

3 Answers3

32

Try:

'ontouchstart' in document.documentElement
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Works great :) checked on Chrome 17, FF9, Safari 5, IE7-9 – Oscar Godson Jan 06 '12 at 20:48
  • @MarcelJackwerth: Let me check that when I get back to Windows, but on Chrome 19 it seems to work fine at least... – Ry- Jun 27 '12 at 15:36
  • failed on Android (gingerbread) - this apparently continues returning false on a touch screen phone. – dragon Jul 24 '12 at 09:00
  • 2
    @dragon: Try one of these tests, then: http://modernizr.github.com/Modernizr/touch.html – Ry- Jul 24 '12 at 14:23
  • @user983693: On which browser? Does the `ontouchstart` event actually work? – Ry- Nov 19 '12 at 14:36
  • @minitech: IE10. But I admit that I should really do a more thorough test though... From what I can recall I ended up using MSPointerDown for the ontouchstart event instead – Maarten Nov 20 '12 at 16:28
  • IE 9.0.8 doesn't fully support touch events. Good piece [here](https://developers.google.com/mobile/articles/fast_buttons): Everything there is supported by Gecko, WebKit, V8. – Dave Feb 13 '13 at 19:05
  • @minitech current Git page: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js – Blazemonger Dec 16 '13 at 19:10
14

Not that you probably don't want to change behavior just because a browser 'supports touch'. Eg. Chrome on Windows now supports touch all the time, even though there won't necessarily be a touch screen attached. Even if there is a touch screen attached, the user doesn't necessarily use it, so you need to be careful with what you change.

So this really comes down to why you want to know:

  1. You want to know whether you're going to get touchstart/touchmove/touchend events: There's really no way to know this in advance for sure. Eg. the user could plug in a touch screen after your page has loaded. If you might be interested in these events, you should just listen for them.

  2. You want to know if you should display a 'mobile' version of your site Whether or not the user has touch support is not the right signal for this - eg. a Windows user with a touch screen probably does NOT want your mobile site. You can use UserAgent heurstics, but please give the user a sticky way to switch versions of your site.

  3. You want to know if you should tweak your UI to be more friendly for touch input Eg., maybe some buttons should be larger if the user is likely to use touch. In general it may be best to always design for multiple pointer types - after all you have no way to know the user's pointer preference when they have both touch and mouse. But if you really want to use knowledge of the pointer hardware available as a hint to making the best UI tradeoff, then there are new CSS media queries you can use:

I added partial support to Chrome for these in Chrome 21 (crbug.com/123062). As far as I know, no other browser supports them yet.

j0k
  • 22,600
  • 28
  • 79
  • 90
Rick Byers
  • 3,136
  • 2
  • 16
  • 13
  • Even this is flaky though. Chrome 25 is reporting that I have pointer:course and hover:0 on a Dell 17 inch laptop. Yes, the laptop has touchscreen support, but it's turned off and I'm using a mouse. That's kind of a problem. (Note that this is starting to impact me with real web apps: http://core.trac.wordpress.org/ticket/20614#comment:34 ) – Otto Nov 13 '12 at 17:27
  • Much agreed, it's good to distinguish between Mobile and Touch. Touch screen on Windows and 10" tablets won't want a touch screen site. However, a lot of developers optimize for touch by replacing onclick events with ontouchstart,etc. to avoid waiting for the double-tap. In this case, pointer detection would be more effective since this encumbers devices with touch AND pointers. – Dave Feb 13 '13 at 18:56
  • Otto: that's how the media queries used to be defined (in terms of the "least capable" of all pointing devices). Based on feedback we've updated the media queries spec and will now be returning pointer: fine, hover: 1 in touchscreen laptop cases (but pointer-any: coarse will return true). See http://dev.w3.org/csswg/mediaqueries4/#mf-interaction. We're hoping to land this in Chrome 38: http://crbug.com/136119. – Rick Byers Jul 24 '14 at 14:03
9
('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch
lafeber
  • 2,683
  • 1
  • 27
  • 29
  • Source: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js#L40 – Matt Jensen Dec 09 '16 at 15:38
  • 3
    `('ontouchstart' in window) || window.DocumentTouch && window.document instanceof DocumentTouch || window.navigator.maxTouchPoints || window.navigator.msMaxTouchPoints ? true : false` – Brian Cannard Feb 28 '17 at 06:56
  • Note that FF team was enabling and disabling touch support many times, and lastly decided to enable it forever in the upcoming 52 release. – Brian Cannard Feb 28 '17 at 06:58