CSS :hover/:focus vs click event on (mobile) touch devices
Asked Answered
R

4

6

Often I am in situations where I need to show a menu on hover and for mobile devices menu should open on click. Now e.g. consider following example:

.btn {
  width: 200px;
  background-color: #333;
  color: white;
  padding: 10px;
}
.menu {
  display: none;
  padding: 15px;
}
.btn:hover .menu {
  display: block;
}
.btn:focus .menu {
  display: block;
}
<div class="btn">
  Button
  <div class="menu">I am menu</div>
</div>

Now this automatically works on mobile devices because hover state is sticky on touch devices. But is this hack applicable to all touch devices? That is, is it worth the risk? Would there be some touch device doesn't have hover state sticky? Obviously the alternative is to assign touch/click events with JavaScript on touch devices but this seem redundant because I haven't seen any touch device which don't have sticky hover states?

So my question is:

Is it okay to use the hover state hack or should I use JavaScript events to make it more bullet proof?

Rejuvenate answered 23/12, 2016 at 14:5 Comment(8)
I'd go with it, should be fine.Swordtail
@Roberrrt Really, I always used this approach in my previous work but now I am getting little suspicious.Rejuvenate
Should be fine.Tableware
The (only) worrying scenario I can come up with is if the element in question isn't focusable, so dropdowns cannot happen on it.Swordtail
@Roberrrt Yes. For non-focusable elements I think hover state is a must.Rejuvenate
Yes, but- there is no such thing as :hover on touch devices :).Swordtail
You can avoid this whole problem if you either use an <a>-element with :target, or an <input type="checkbox"> with :checked - as far as I know, no browser even considers mangling link/form-functionality.Unreliable
@Unreliable Although that kinda defeats the hover state, but then again you can use media queries to only enable this on small devices.Swordtail
U
3

I'd say it's fine to just stick with the css for most hovers, as long as you're okay with the menu or whatever closing when a user clicks a separate element.

I'm not aware of any mobile browsers that don't adhere to this behavior, at least not major ones. If any of the major browsers dropped this, a huge chunk of the mobile web would need rebuilt.

Probably safe!

Unfrequented answered 23/12, 2016 at 14:18 Comment(1)
Yeah, you have a valid point. A whole lot of websites would work incorrectly if this behavior isn't adhered by some device or browser.Rejuvenate
S
3

In my experience, this isn't really a hack but more of a way to imitate hover events with pure CSS. I mainly use the :hover/:focus for these kind of issues, because

1.) They're reliable.

2.) Cheap (in terms of kb).

It takes only 2 rules and no external HTTP request to include a rule for a fully functioning menu, but several lines of JavaScript (or, the horror, jQuery) to create the same thing.

What I said in the comments, you should or could enforce the tabindex attribute to force an element to be focusable, such like:

<div class="non-focusable-clickable-hover-element" tabindex="-1">I cannot be focussed<div>

<div class="focusable-hover-element" tabindex="1">I can be focussed<div>
Swordtail answered 23/12, 2016 at 14:32 Comment(0)
C
3

From my experience this does not work reliably. It may have at one time or another. But it does not with current browsers in 2020.

Better is to use media queries for pointer of type coarse:

@media(hover: none) and (pointer: coarse){
... CSS styling in here ...
}

Medium article on targeting touch devices

This works on all browsers except IE MDN details

Collins answered 10/9, 2020 at 23:48 Comment(2)
Where didn't this work reliably in 2020?Reinert
@Reinert - The suggested solution that user31782 provides did not work on iPhone consistently. Consistently is the important word. At this time I can not remember which browser had the issue. Yet as we only tested iPhone for Safari or Chrome at my past employer, it must have been one of these. Sorry I can not be of more help.Collins
C
0

.btn {
  width: 200px;
  background-color: #333;
  color: white;
  padding: 10px;
}
.menu {
  display: none;
  padding: 15px;
}
.btn:hover .menu {
  display: block;

}
.btn:focus .menu {
  display: block;
}
<div class="btn">
  Button
  <div class="menu">I am menu</div>
</div>
Countrified answered 13/9 at 19:10 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Kuhl

© 2022 - 2024 — McMap. All rights reserved.