All of these have a touch screen
This is a great visual example of why you shouldn’t assume that having a touch screen always equals a phone or tablet.
This is a great visual example of why you shouldn’t assume that having a touch screen always equals a phone or tablet.
In Resilient Web Design Jeremy Keith discusses the idea of material honesty. He says that “one material should not be used as a substitute for another, otherwise the end result is deceptive”.
Making a link look like a button is materially dishonest. It tells users that links and buttons are the same when they’re not.
In Buttons In Design Systems Nathan Curtis says that we should distinguish links from buttons because “button behaviours bring a whole host of distinct considerations from your simple anchor tag”.
For example, we can open a link in a new tab, copy the address or bookmark it for later. All of which we can’t do with buttons.
Whatever you may think, it currently isn’t possible to reliably detect whether or not the current device has a touchscreen, from within the browser.
And it may be a long time before you can.
Let me explain why…
Boxed in
The browser environment is a sandbox. Your app’s code can only get at things the browser wants you to, in order to limit the damage a malicious website can cause.
This means that the only information about the system you can get is what the browser exposes to you, in the form of HTML, CSS and JavaScript APIs. To determine if a system supports a certain feature, we can a) see if a certain API is present, or b) see if it actually does the right thing.
Historically, two browser features have been used for “touchscreen detection”: media queries and touch APIs. But these are far from foolproof.
Walk with me.
Device width media queries
Mobiles have small screens and mobiles have touchscreens, so small screen equals touchscreen, right?
[…]
So, so very wrong. Large tablets and touchscreen laptops/desktops have clearly proven this wrong. Plus thousands of older mobile handset models had small non-touch screens. Unfortunately, sites applying the mantra “If it’s a small screen, it’s touch; if it’s a big screen, it’s mouse-driven” are now everywhere, leaving tablet and hybrid users with a rubbish experience.
Touch APIs
[…]
If the browser supports events like
touchstart
(or other events in the Touch Events API spec) it must be a touchscreen device, right?[…]
Well, maybe. The problem is, no one ever said that a non-touch device can’t implement touch APIs, or at least have the event handlers in the DOM.
Chrome 24.0 shipped with these APIs always-on, so that they could start supporting touchscreens without having separate “touch” and “non-touch” builds. But loads of developers had already used detects like the example above, so it broke a lot of sites. The Chrome team “fixed” this with an update, which only enables touch APIs if a touch-capable input device is detected on start-up.
So we’re all good, right?
Not quite.
An API for an API
The browser is still quite a long way from the device itself. It only has access to the devices via the operating system, which has it’s own APIs for letting the browser know what devices are connected.
While these APIs appear to be fairly reliable for the most part, we recently came across cases whereby they’d give incorrect results in Chrome on Windows 8… they were reporting presence of a touchscreen (“digitizer”), when no touchscreen was connected.
Firefox also does some kind of similar switching and it appears to fail in the same cases as Chrome, so it looks like it might use the same cues – although I can’t profess to know for sure.
It appears certain settings and services can mess with the results these APIs give. I’ve only seen this in Windows 8 so far, but theoretically it could happen on any operating system.
Some versions of BlackBerry OS have also been known to leave the touch APIs permanently enabled on non-touch devices too.
So it looks like the browser doesn’t know with 100% confidence either. If the browser doesn’t know, how can our app know?
Drawing a blank
Assuming the presence of one of these touch APIs did mean the device had a touchscreen… does that mean that if such a touch API isn’t present then there definitely isn’t a touchscreen?
Of course not. The original iPhone (released in 2007) was the first device to support Touch Events, but touchscreens have been around in one form or another since the 1970s. Even recently, Nokia’s Symbian browser didn’t support touch events until version 8.2 was released last year.
IE 10 offers the (arguably superior) Pointer Events API on touch devices instead of the Touch Events spec, so would return
false
for theontouchstart
test.[…]
Neither Safari nor Opera has implemented either touch API in their desktop browsers yet, so they’ll draw a blank on touch devices too.
Without dedicated touch APIs, browsers just emulate mouse events… so there are loads of devices kicking about with touchscreens which you simply can’t detect using this kind of detection.
[…]
You’re doing it wrong
In my opinion, if you’re trying to “detect a touchscreen” in the first place, you’re probably making some dangerous assumptions.
[…]
So what should I do?
For layouts, assume everyone has a touchscreen. Mouse users can use large UI controls much more easily than touch users can use small ones. The same goes for hover states.
For events and interactions, assume anyone may have a touchscreen. Implement keyboard, mouse and touch interactions alongside each other, ensuring none block each other.
Typically we would view shorthand syntax as a benefit: fewer keystrokes, fewer lines of code, less data over the wire. Sounds great! However, it comes with a rather troublesome side effect: it often unsets other properties that we never intended to modify.
When we write something like:
.btn {
background: red;
}
…we’re likely to get a red background colour applied to our button. But what we’re really saying is this:
.btn {
background-image: initial;
background-position-x: initial;
background-position-y: initial;
background-size: initial;
background-repeat-x: initial;
background-repeat-y: initial;
background-attachment: initial;
background-origin: initial;
background-clip: initial;
background-color: red;
}
Simply by using the shorter syntax, we have implicitly decided that we want no image to start top-left, repeat x and y, to scroll with the element, and so on…
Nearly every problem, bug, or regression in CSS at scale is happens because we did too much too soon, and further down the line we’re being affected by that. What this basically comes down to is the fact that, with CSS, you should only ever do as little as you need to do and nothing more.
Misusing shorthand syntax is a surefire way to do too much too soon, as thus it should be avoided. CSS is a lot harder to undo than it is to do.