How to detect if device is touchscreen?

Hi, I'm trying to make a component a little more user friendly by applying certain CSS rules based on the user's device. If it's a touch screen I'd like to permanently show some buttons, whereas on a regular computer those buttons would appear only when hovered over with the mouse. Since there are touch screens even for desktop computers these days, I will probably use additional media queries to restrict this based on the window dimensions. But I will worry about that later. For now, I was wondering what's the most effective way of doing this using CSS only. With JavaScript I've used something like this before:
navigator.userAgent.match(
/(Android|iPhone|iPad|iPod|webOS|Windows Phone|BlackBerry)/i
);
navigator.userAgent.match(
/(Android|iPhone|iPad|iPod|webOS|Windows Phone|BlackBerry)/i
);
This works fine for the most part but, since I'm only interested in applying some styles, I'd prefer not to mix things if possible. According to MDN there are two media queries that might work for me but I've never used them: any-hover and hover, has anyone used them before and which one would you recommend? Thank you! https://developer.mozilla.org/en-US/docs/Web/CSS/@media
9 Replies
Jochem
Jochem4mo ago
MDN Web Docs
pointer - CSS: Cascading Style Sheets | MDN
The pointer CSS media feature tests whether the user has a pointing device (such as a mouse), and if so, how accurate the primary pointing device is.
Jochem
Jochem4mo ago
though I haven't used it, nor the hover ones
Joao
Joao4mo ago
This looks also good enough, I'll give this a try first and see how it goes. Thanks!
Kevin Powell
Kevin Powell4mo ago
The pointer media query is awesome, but there is a lot of gray zones with it, and some edge cases can come up, so it's important to know that's possible... but afaik, it's also the best we have 😄
Joao
Joao4mo ago
My main concern is what happens when there's a laptop with a touch screen but has a mouse attached... which one takes precedence? Or maybe it depends on the input used each time. I really don't want to end up with a complex media query just for this, but for now though it works fine so I'll worry about it if and when I have to. 🙂
Jochem
Jochem4mo ago
the spec could give you a hint: https://drafts.csswg.org/mediaqueries/#pointer It says when there's multiple, the user agent gets to determine which is "primary". No indication of how it does it though
Joao
Joao4mo ago
It says that it uses the user agent, I guess it relies on whether it's some sort of mobile device or not? But it looks like for a more sophisticated media query the any-pointer may be a better option or, based on some answers on SO, a combination of pointer: coarse and hover: none. Well, another rabbit hole that I don't want to jump into right now 🐰 but thanks again for suggestion, it works fine for me simple case at the moment
Jochem
Jochem4mo ago
The user agent in this context isn't the string that you can request in javascript, but the browser itself. But yeah, any-pointer might work if you have issues, though my (baseless) assumption would be that a multi-input device would report the most recently used input method as primary? Anyway, hope it solves your issue!
Joao
Joao4mo ago
It did, at least for now so I'll just leave it at that at the moment. Thanks again for the find, much appreciated!