What's the best way to detect a 'touch screen' device using JavaScript?

UPDATE 2021

To see the old answers: check the history. I decided to start on a clean slate as it was getting out of hands when keeping the history in the post.

My original answer said that it could be a good idea to use the same function as Modernizr was using, but that is not valid anymore as they removed the "touchevents" tests on this PR: https://github.com/Modernizr/Modernizr/pull/2432 due to it being a confusing subject.

With that said this should be a fairly ok way of detecting if the browser has "touch capabilities":

function isTouchDevice() {
  return (('ontouchstart' in window) ||
     (navigator.maxTouchPoints > 0) ||
     (navigator.msMaxTouchPoints > 0));
}

But for more advanced use cases far more smarter persons than me have written about this subject, I would recommend reading those articles:

  • Stu Cox: You Can't Detect a Touchscreen
  • Detecting touch: it's the 'why', not the 'how'
  • Getting touchy presentation by Patrick H. Lauke

Update: Please read blmstr's answer below before pulling a whole feature detection library into your project. Detecting actual touch support is more complex, and Modernizr only covers a basic use case.

Modernizr is a great, lightweight way to do all kinds of feature detection on any site.

It simply adds classes to the html element for each feature.

You can then target those features easily in CSS and JS. For example:

html.touch div {
    width: 480px;
}

html.no-touch div {
    width: auto;
}

And Javascript (jQuery example):

$('html.touch #popup').hide();

As Modernizr doesn't detect IE10 on Windows Phone 8/WinRT, a simple, cross-browser solution is:

var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;

You only ever need to check once as the device won't suddenly support or not support touch, so just store it in a variable so you can use it multiple times more efficiently.