Touchscreen detection

Uses a series of APIs / media feature tests to try and determine if a touchscreen is present.

function detectTouchscreen() {
  var result = false;
  if (window.PointerEvent && ('maxTouchPoints' in navigator)) {
    // if Pointer Events are supported, just check maxTouchPoints
    if (navigator.maxTouchPoints > 0) {
      result = true;
    }
  } else {
    // no Pointer Events...
    if (window.matchMedia && window.matchMedia("(any-pointer:coarse)").matches) {
      // check for any-pointer:coarse which mostly means touchscreen
      result = true;
    } else if (window.TouchEvent || ('ontouchstart' in window)) {
      // last resort - check for exposed touch events API / event handler
      result = true;
    }
  }
  return result;
}

Detection logic

  1. If Pointer Events are supported, it will just check the navigator.maxTouchPoints property. The script omits the vendor-prefixed version of Pointer Events (e.g. navigator.msMaxTouchPoints), as that was only supported in IE10.
  2. If Pointer Events are not supported, it checks the any-pointer:coarse interaction media feature using window.matchMedia. It does not test for Firefox's proprietary -moz-touch-enabled feature, as that is simply a CSS reflection of whether or not Touch Events are enabled (see next test).
  3. As a last resort, it checks for Touch Events support (which in older browsers, which do not support the preceding tests, is generally only exposed when the browser is running on a touchscreen device).

Note that the presence of a touchscreen still does not guarantee that a user will actually use the touchscreen, as it does not guarantee that there are no other input devices (including mice or keyboards) that the user may use instead. Further, it's always possible that a user may add or enable a touchscreen after the detection was done (for instance, plugging in an external touchscreen monitor). And lastly, a touchscreen being present doesn't mean this is a mobile or tablet device, as there are touch-enabled laptops and desktops. So...use this detection with caution and a big pinch of salt, and understand what it is that you're actually detecting here.

See Getting touchy - everything you (n)ever wanted to know about touch and pointer events for more context and information.