10

Everyone has been pushing towards feature detection for a long time. I'd like to detect if a visitor's browser supports the :hover pseudo class. It's my understanding there are enough, if not most, mobile devices that do not support hovering, so I'd like to gear my event listeners accordingly. But without mobile detection, I'm unsure how to accomplish this, and I've not found anything via Google or SO thus far.

Perhaps something similar to question #8981463

$(function() {
  var canHover = $(document).is(":hover");
});

I won't be able to test this on a mobile device 'till next week.

Thoughts?

Community
  • 1
  • 1
Keith DC
  • 661
  • 1
  • 9
  • 24
  • 1
    I'm not sure if this will help, but, I'll leave them all here for you to look over: http://api.jquerymobile.com/vmouseover/, http://www.izilla.com.au/git/jquery.izilla.touchMenuHover.html, http://www.prowebdesign.ro/how-to-deal-with-hover-on-touch-screen-devices/, https://forum.jquery.com/topic/help-with-hover-effect-on-touchscreens-and-mobile-devices, – adamj May 09 '14 at 05:50
  • Again: why do you want to detect the `hover`-ability? In general to tell if it's a mobile device? To disable hovering for mobile devices? – try-catch-finally May 09 '14 at 05:57
  • 1
    Hope this makes sense, but I have some small aesthetic events firing on hover over a clickable (menu) button. But my brother let me know their audience is primarily mobile-based. I can adjust the code to suit mobile better, but then it becomes a little strange behavior for non-mobiles, such as having to click the button twice to activate it, or click the button to get a dropdown menu. If I detect the hover-ability, I can still allow non-mobile users to hover, which is more expected behavior. – Keith DC May 09 '14 at 06:03
  • 1
    Sounds like the hover will show some animation (on or beside the button). Or do you show kind of a submenu? You might completely change the usability ob the website for mobile users as they have completely different needs (not wasting space, distraction free content and navigation, save battery, short loadtimes on slower networks, ...). For example, an animation that's only for an aestetic reason might be uninteresting (if the website is not all about that animation). – try-catch-finally May 09 '14 at 06:22
  • I asked something simular a few months ago, there is a [plugin](http://stackoverflow.com/questions/22933770/will-this-event-handling-code-work-on-all-touch-devices) – AME May 09 '14 at 06:57
  • @try-catch-finally, I do plan on not showing any animation on screens with a vertical smaller than say, 600px, but touch-screen monitors are becoming more commonplace as well. – Keith DC May 09 '14 at 06:57

3 Answers3

11

There is now a well-supported media query to detect whether hover is supported: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover

Which you can use with Window.matchMedia: https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia

Then you would use:

if (window.matchMedia( "(hover: none)" ).matches) {
   // hover unavailable
}
mandelf
  • 470
  • 6
  • 5
  • That's a great option if you want to keep things consistent between your javascript and your CSS. Furthermore, interaction media queries are now fully-supported: https://caniuse.com/#feat=css-media-interaction. – tavoyne Jun 06 '20 at 10:17
8

There is no is(':hover'), you can't detect CSS pseudo classes with javascript as they are not part of the DOM.

You can however detect certain events that are only available on touch screens and act accordingly, modernizer does something like this

if ('ontouchstart' in document.documentElement) {
  document.documentElement.classList.add('touch');
} else {
  document.documentElement.classList.add('no-touch');
}

where it adds classes to the <html> element that tells you wether or not the device has a touch screen or not, so you can do something like this in CSS

.no-touch .element:hover {color: red;} // for users with a mouse
.touch .element {color: blue;} // for touch devices
Community
  • 1
  • 1
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • Thanks for the input, Adeneo. I appreciate your avoiding suggesting my implementing modernizer or such, as this is a small site, and I'd rather not have to implement that for one detection purpose. However, if all else fails... I may need to go that route. But your above suggestion looks promising. – Keith DC May 09 '14 at 06:10
  • You could create the entire code just as easy; Just make a check whenever an user opens the page. For instance when someone just hovers over the body of the page. If one hovers over the body, then you know that user has the hover function. You can then give every object you want to check whether or not is has hover a class. – Daan May 09 '14 at 06:46
-3

Couldn't sleep, and may have figured it out, at least perhaps for my particular situation. I use sprites on these buttons and I'm already doing sprite position checks elsewhere. My thought is when the button is clicked, prior to firing, it can also do the sprite position check. If the sprite hasn't been re-positioned for the clicked button, it would seem it is not a hover-able device, and I can treat the click as the 1st of a 2-part activation. I read earlier today that some mobile devices do that already, in that they treat the 1st click as the hover.

My sprite positioning logic as as such, and perhaps could be called prior to the button's click-fire event:

if ($(elem).css('background-position').indexOf('76px') >= 0 ) {
Keith DC
  • 661
  • 1
  • 9
  • 24
  • Note that `background-position-y` is non-standard and not part of any CSS specification, so there's no guarantee the browser will support it, and I don't think Firefox does. – adeneo May 09 '14 at 07:18
  • @adeneo, you are quite correct, so I'll look to do an indexOf on 'background-position', which does report back, but it's worse than that. FF isn't reporting the new hovered position, and instead, provides back the initial position. I'll need to check into that, perhaps an event ordering issue, but hoping the concept of this approach will work. If not, I'll defer to your 'ontouchstart' approach. I'll look to report back this weekend. Thanks again for the insight. – Keith DC May 09 '14 at 14:59
  • I believe going with my sprite position detection, although perhaps more JS work, will also accommodate users with mice on touchscreen devices. If using the mouse, the :hover pseudo class will alter the background-position. If the button is clicked, and the position isn't what it should be according to the :hover pseudo class, I can alter the position directly, and then trigger the 'mouseenter' listener. If the button is clicked and the position is correct, then either the mouse clicked once, or touchscreen has already clicked once. – Keith DC May 12 '14 at 20:24
  • Unsure when it happened, but all browsers now support this property. https://developer.mozilla.org/en-US/docs/Web/CSS/background-position-y#browser_compatibility – Keith DC Sep 11 '21 at 02:11