We have all been there! You make a responsive web site, add some hover effects as usual.
You try out the site on your touch device, and suddenly strange things start to happens to all kinds of elements when you scroll.
That’s because as soon as you touch the elements, but don’t click them, the browser triggers the hover state.
A lot of really good developers out there want us to treat the desktop users and the touch users the same. But they don’t have the same possibilities, so why?. Just because touch users can’t use the hover state properly, doesn’t mean we shouldn’t aid the desktop users. It helps a lot when navigation around a page!
However, when you use hover effects, beware that your touch users won’t get any help from it. So don’t, for example, rely on tool tips and let the touch users hang dry.
So to allow the desktop users and touch devices to coexist we simply remove the hover effects for touch devices.
It would be super simple if you could use Modernizr to test whether it’s a touch device or not.
But you can’t This method cannot be trusted. There are just to many false positives stacking up.
For example, with the update of Firefox to version 36, my desktop at work report that it’s a touch device. So is Chrome on one of the laptops the testers use in my project.
The only way you can reliably detect a touch device, that I know of, is to listen for an actual touch.
To do this can use a the JavaScript below.
First do I quick and dirty check in case you need to condition something during page load, and the we add a touch test which will only be fire in case a user actually has a touch device.
Note: The second test will not fire until the user actually touch the screen.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
(function() { //I use jQuery for simplicity var preliminaryTouch = false; //Assume all devices are no touch device $('html').addClass('no-touch-device'); //Check the user agent string if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) { preliminaryTouch = true; } if( preliminaryTouch ) { //Do something for touch devices and //Add a preliminary touch class $('html').addClass('prel-touch-device'); } })(); $(document).on('touchstart', function() { //Now we can safely remove the the no-touch-device and prel-touch-device classes $('html').removeClass('no-touch-device prel-touch-device').addClass('touch-device'); }); //Do something later somewhere in your code if( $('html').hasClass('touch-device') ) { //Do something for touch devices } |
Please also note that until we actually know if it’s a real test device or not, the divice will be both touch device and not. Like Schrödinger’s cat or a quantum state.
So now we have the JavaScript in place. Lets move on to the CSS.
You can use the following states, although you should try to avoid using anything else then the ‘no-touch-device’ class, which is the default class for all devices before the test is done.
|
1 2 3 4 5 6 7 8 9 10 11 |
html.no-touch-device { /* This style will be applied form the beginning, and continue to exist unless the second test shows it's a touch device */ } html.prel-touch-device { /* If the preliminary test shows it's a touch device you can use this to apply styles. This will rarely be used in the CSS. But might be handy in the JavaScript early on in the code flow. */ } html.touch-device { /* Here you add the styles that only the touch devices should use. Try to avoid it as much as possible. */ } |
This is what a real example would like in your stylesheet
|
1 2 3 4 |
/* This will not affect touch devices */ html.no-touch-device a:hover { font-weight: bold; } |
Try a live example here:
See the Pen WbKbaN by Jon WAllsten (@JonWallsten) on CodePen.