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>
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?
Share Improve this question edited Dec 23, 2016 at 14:14 roberrrt-s 8,2102 gold badges49 silver badges60 bronze badges asked Dec 23, 2016 at 14:05 user31782user31782 7,58716 gold badges78 silver badges157 bronze badges 8- I'd go with it, should be fine. – roberrrt-s Commented Dec 23, 2016 at 14:08
- 1 @Roberrrt Really, I always used this approach in my previous work but now I am getting little suspicious. – user31782 Commented Dec 23, 2016 at 14:10
- Should be fine. – Jeroen Commented Dec 23, 2016 at 14:16
- The (only) worrying scenario I can e up with is if the element in question isn't focusable, so dropdowns cannot happen on it. – roberrrt-s Commented Dec 23, 2016 at 14:23
-
1
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. – junkfoodjunkie Commented Dec 23, 2016 at 14:44
4 Answers
Reset to default 3I'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!
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 ments, 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>
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
.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>