I'd like to provide separate behaviour for browsers supporting hover (e.g. desktop browsers) and ones which don't (e.g. touchscreen devices). Specifically I want to declare a hover state on browsers that support it, but not for browsers that don't, so as to avoid having mobile browsers emulate it with extra taps, as this breaks other interactions on the page - by not defining a hover state for those browsers this is avoided.
I've read up on the Interaction Media Queries feature and it looks like it should do the trick. I'd be able to do something like:
@media (hover: none) {
/* behaviour for touch browsers */
}
According to CanIUse it is available on all the browsers I need to support except IE11 and Firefox.
So I wondered if I could do it the other way around - since the main touch devices all support it, then negate it:
@media not (hover: none) {
/* behaviour for desktop browsers */
}
However, this doesn't seem to work at all.
Pseudocode example of what I'm trying to do:
.myelement {
/* some styling */
/* note: no hover state here */
}
@media(this device supports hover) {
.myelement:hover {
/* more styling */
}
}
So, is there a way to make this work in the way intended, or am I down the wrong track?
To support Firefox (see https://bugzilla.mozilla.org/show_bug.cgi?id=1035774 ), you need to potentially write some rules twice. Note, although not specified in the question I've added
pointer: coarse
on the assumption that the purpose of these rules is to target mobile screens:The combination of
(pointer: coarse) and (hover: none)
should become more useful to target mobile devices as mobile screens become larger and we lose the correlation between pixel dimensions and mobile vs. desktop (already the case when you wish to distinguish between tablet and desktop)According to Artin´s answer we can address only devices that support hover with pure css, with
@media not all and (hover: none)
. It looks weird but it works.I made a Sass mixin out of this for easier use:
The following would change background-color of
.container
from red to blue on hover for devices that support hover, no change for touch devices:From the specs:
If your browser (mobile/touch) support long-press to simulate hover, the usage of
hover: none
will not work. What you can do is just use a default value and override it (with default css precedence):Desktop will have
blue
background and mobile/touch will havered
backgroundCheck the following example:
https://jsfiddle.net/mcy60pvt/1/
To check the long-press option of the mobile you can use this example:
https://jsfiddle.net/mcy60pvt/3/
In the above example the green block has
:hover
definition for both desktop and mobile, however for desktop the background will change toyellow
and for mobile (with long-press) it will change towhite
.Here is the css for the last example:
In this example - browsers that don't support
:hover
will view the hover me box with green background, and while "hover" (touch/long-press) - the background will change to white.update
As for the added pseudo code:
Thanks to Dekel's comments I solved this by running the logic in JS and applying a class instead:
e.g.
Then in the stylesheet:
I've tested this on desktop Chrome, Safari and Firefox, and iOS Safari and it works as expected.
not
should prefix media type (screen, print, all, etc) and not media feature (hover, point, etc).Wrong:
Correct:
Yes, its unintuitive and weird. Source (see comments).
So you do not need javascript to alternate result of media query.