Media query to detect if device is touchscreen

The CSS solutions don't appear to be widely available as of mid-2013. Instead...

  1. Nicholas Zakas explains that Modernizr applies a no-touch CSS class when the browser doesn’t support touch.

  2. Or detect in JavaScript with a simple piece of code, allowing you to implement your own Modernizr-like solution:

    <script>
        document.documentElement.className += 
        (("ontouchstart" in document.documentElement) ? ' touch' : ' no-touch');
    </script>
    

    Then you can write your CSS as:

    .no-touch .myClass {
        ...
    }
    .touch .myClass {
        ...
    }
    

Nowadays, CSS Media queries can be used to define style for devices with specific interactive features and it's widely supported as well.

hover for example can be used to test whether the user's primary input mechanism can hover over elements (which would not be true in touch-enabled devices without emulating)

@media (hover: none) {
  a {
    background: yellow;
  }
}

Other interactive tests are: pointer, any-pointer, hover, and any-hover

Previous answer

I would suggest using modernizr and using its media query features.

if (Modernizr.touch){
   // bind to touchstart, touchmove, etc. and watch `event.streamId`
} else {
   // bind to normal click, mousemove, etc.
}

However, using CSS, there are pseudo class like, for example in Firefox. You can use :-moz-system-metric(touch-enabled). But these features are not available for every browser.

For Apple devices, you can simply use:

if (TouchEvent) {
   //...
}

Especially for iPad:

if (Touch) {
    // ...
}

But, these do not work on Android.

Modernizr gives feature detection abilities, and detecting features is a good way to code, rather than coding on basis of browsers.

Styling Touch Elements

Modernizer adds classes to the HTML tag for this exact purpose. In this case, touch and no-touch so you can style your touch related aspects by prefixing your selectors with .touch. e.g. .touch .your-container. Credits: Ben Swinburne


There is actually a property for this in the CSS4 media query draft.

The ‘pointer’ media feature is used to query about the presence and accuracy of a pointing device such as a mouse. If a device has multiple input mechanisms, it is recommended that the UA reports the characteristics of the least capable pointing device of the primary input mechanisms. This media query takes the following values:

‘none’
- The input mechanism of the device does not include a pointing device.

‘coarse’
- The input mechanism of the device includes a pointing device of limited accuracy.

‘fine’
- The input mechanism of the device includes an accurate pointing device.

This would be used as such:

/* Make radio buttons and check boxes larger if we have an inaccurate pointing device */
@media (pointer:coarse) {
    input[type="checkbox"], input[type="radio"] {
        min-width:30px;
        min-height:40px;
        background:transparent;
    }
}

I also found a ticket in the Chromium project related to this.

Browser compatibility can be tested at Quirksmode. These are my results (22 jan 2013):

  • Chrome/Win: Works
  • Chrome/iOS: Doesn't work
  • Safari/iOS6: Doesn't work