Media query for devices supporting hover
not
should prefix media type (screen, print, all, etc) and not media feature (hover, point, etc).
Wrong:
@media not (hover: none)
Correct:
@media not all and (hover: none)
Yes, its unintuitive and weird. Source (see comments).
So you do not need javascript to alternate result of media query.
Thanks to Dekel's comments I solved this by running the logic in JS and applying a class instead:
e.g.
const canHover = !(matchMedia('(hover: none)').matches);
if(canHover) {
document.body.classList.add('can-hover');
}
Then in the stylesheet:
.myElement {
background: blue;
}
.can-hover .myElement:hover {
background: red;
}
I've tested this on desktop Chrome, Safari and Firefox, and iOS Safari and it works as expected.
From the specs:
none
Indicates that the primary pointing system can’t hover, or there is no pointing system. Examples include touchscreens and screens that use a drawing stylus.
Pointing systems that can hover, but for which doing so is inconvenient and not part of the normal way they are used, also match this value.For example, a touchscreen where a long press is treated as hovering would match hover: none.
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):
body {
background: red;
}
@media (hover: hover) {
body {
background: blue;
}
}
Desktop will have blue
background and mobile/touch will have red
background
Check 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 to yellow
and for mobile (with long-press) it will change to white
.
Here is the css for the last example:
body {
background: red;
}
div.do-hover {
border: 1px solid black;
width: 250px;
height: 250px;
background: green;
}
div.do-hover:hover {
background: white;
}
@media (hover: hover) {
body {
background: blue;
}
div.do-hover:hover {
background: yellow;
}
}
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:
.myelement {
/* some styling #1 */
/* note: no hover state here */
}
@media(hover: hover) {
.myelement {
/* some styling that override #1 styling in case this browser suppot the hover*/
}
.myelement:hover {
/* what to do when hover */
}
}