This article is some very drafty personal notes, although, I might not further improve it neither.
Recently, I've been working to adopt our PC app onto tablets for acceptable user experience Conclusion: Do not display critical information nor put critical UX path in something triggered by a hover gesture.
Background: Tablets are acting more and more like a PC
After iPadOS, Apple is making iPad act much more like a desktop. I have an earlier rant about how it is nearly funnily inconvenient to tell iPad apart from a Mac. And users may simply browse your website on a tablet and see your site which is optimized for a computer.
One of the fixes and optimizations we have to do, then, is to deal with the hover gesture, a UI gesture that is prevailent on PC but not consistently available on tablets.
Inconsistent triggerers of :hover
across different devices
Tapping on newer iPads (after iPadOS) will trigger the :hover
pseudo class (I specifically use this because the React mouse enter event is another story, which we'll mention later). And is fairly consistent.
But older iPads and Android tablets won't. To trigger the :hover
pseudo class, users need to touch the tablet surface as if touching their eyeballs. Over the course of my project, I've learned to trigger this with fairly positive confidence level -- what you do is you lightly touch the target element and then you move your finger, like dragging. It's quite a specific movement that users may not even associate with the element, so when I explain to PMs and designers that this is not something we'd expect our users to be able to learn, they all agree.
Elements with both hover-to-display information and click-to-navigate event
Remember how on newer iPads, :hover
will be triggered by a tap. What we also observe is that in such elements, if a click-to-navigate event is also present, its trigger will be delayed to a second tap.
This is a considerable UX change that leads to rejection by some of our feature PMs. This is understandable too, as the click-twice-to-navigate is not in their original attention when they designed the feature.
And of course, what's worse is in some tablets that hover is highly unlikely ever triggered at all, because of its hidden and inconsistency nature on the tablets. So, it's a very bad idea to display any key information, or critical UX path in something that's triggered by a hover gesture.
:hover
is not the same with React's onMouseEnter
This is another situation I encountered.
PM: on element A, hover is converted to a click, but on element B is not, click will directly click. Can I make element B have the same effect as element A (and in some case, the other way around)?
You may first observe that the PM's word choice of the situation is limited and not very accurate. As a developer we may learn immediately what is going on (element B is implemented with onMouseEnter
), and I need to refrain myself from enriching their disctionary here by explaining the difference between a CSS :hover
pseudo element, React's onMouseEnter
, and how browsers treat them differently.
But really, I haven't found a quick answer to how we can make use of the browser's treatment of :hover
on the events implemented by React's onMouseEnter()
and onMouseLeave()
synthetic events. Very naïvely, say we want to use click
in place of hover on tablets, we can detect whether the device has :hover
with window.matchMedia()
:
const hoverAction = // ...
const doNothing = () => {};
const hasHoverGesture = () => !!window.matchMedia(`(hover: hover)`);
render(<div
onMouseEnter={hasHoverGesture() ? hoverAction : doNothing}
onClick={hasHoverGesture() ? doNothing : hoverAction}
>hover me</div>);
But of course, this cannot utilize some tablets' differentiation of a tap and a click, which some users may have learned how to trigger respectively.