Bootstrap - Different behavior (hover/click)

I’m hoping that someone (cough @PaulOB) might be able to know some tricks that I don’t know of.

I’ve got an odd situation here I don’t know how to handle where I need to present the same data two different ways depending on whether they hover or if they click.

Note: I’m using Bootstrap. Non-negotiable.

Starting point , REALLY dumbed down here: https://codepen.io/davemaxwell/pen/NWRLoMX

I’ve got a menu with sub-menus. If the user clicks on the parent item, they want it to accordion down like in the menu1 in the example. Easy, peasy and done. HOWEVER, the curveball I’m running into is they also want to be able to hover over the parent item and have the hover behavior like in menu 2.

What I’ve been trying to figure out is how to have both behaviors off of one link while trying not to have duplicate markup(nor have BOTH items go at the same time). I’ve spent the past couple hours on it, and I certainly can’t figure it out.

Yes that is the curveball, or in baseball terms… a greaseball.

I’m sure this must be a request from your client.

If I’m on a desktop and I hover over the menu (in order to get to it to click it) the menu opens as a hover menu should. How am I going to know that I can click it to do what’s already been done? That is, why would I want to click it to open a menu that is already open.

As we all know, mobile devices and small screens that don’t support hover get a click menu. But isn’t that for smaller screens by way of media queries. I mean I know you can have a click menu on desktops but it seems redundant to try and have a click-or-hover menu for desktops. I would expect one or the other.

You can detect for touch devices and add a class to the html element and then use that class to avoid applying hover styles to mobile (as that confuses them if they also have a click routine) and then also use that class in the js to create the click menu for touch only.

Here’s an old example but its not a dropdown effect.

I’m out for the morning but will see if I can find a better example later.

A quick fix would be just to use the any hover media query and produce a flyout for hover only leaving the click effect in place.

e.g.

@media (any-hover: hover) {
  .menu-item:hover > ul {
    display: block;
   height: auto !important;
  }
}

You’ll have to style it to suit but you can do that in the media query.

The only problem is that when someone clicks the menu then the menu stays open and if you click it again to close it then you are hovering it so it stays open until you hover away (catch 22 in effect :slight_smile: ).

You could disable the click action when it is hovered using pointer-events:none like so;

@media (any-hover: hover) {
  .my-menu {
    z-index: 99;
    position: relative;
  }
  .my-menu .menu-item:hover > ul {
    display: block;
    height: auto !important;
  }
  .my-menu .menu-item:hover .menu-link {
    pointer-events: none;
  }
}

All the above would need testing first before you implement for real.:slight_smile:

Here’s another version that checks for touch before implementing the js and then use any-hover just for hover devices.

I’m sure a mixture of those methods will achieve what you want. :wink:

Actually, it’s from our UI guru :shifty:

Good questions, and what I’ve been wracking my brains since I found the requirement,

I’ll definitely have to account for touch devices after I get this bit working.

Hmmm…good to know I wasn’t far off on that approach. I just couldn’t figure out how to get the two different stylings on the same object depending on the action taken on them.

I’m on a bit of a time crunch, so for expedience sake, I might clone the object in JS and apply the hover stylings on the cloned object (assuming the clicked event hasn’t happened) and see if I can come up with a more elegant solution once we’re past this demo (which this is needed for)

Thanks to both of you for the guidance. This one just threw me for a loop…

Touch devices treat a first touch as a hover so you really need to keep hover styles away from touch devices otherwise they activate the menu but won’t hide it. e.g.When you have a click action you still can’t hide it because you touched it first. That’s why you need the any-hover media query to stop touch getting the hover styles.

The any-hover media query css code I offered above will do all that easily :slight_smile:

Also remember that when you hover an element you do not really want the hovered menu to be part of the flow as that will push the whole page down and is a UI nightmare (and bad for those with epilepsy). Click menus can be in the flow as they don’t flick on and off all the time but if a hover menu does that its very bad practice.

You may have missed the last demo which I think is the best way to address this. Only touch devices get the JS click action and only hover devices get the hover menu.

Good luck anyway.

Oh, I thought you were wanting hover devices to have the option to click or hover the menu open.

1 Like

Yes, that’s what it sounded like but as you and I pointed out you can’t click a menu without hovering it first so you can’t have both work successfully. It will work but is usability nightmare. :slight_smile:

1 Like

This is definitely not my first choice of behavior but our UI person is insistent :frowning:

I managed to get it working where the hover/click is not too obtrusive. Not showing the hovered menu whenever the button has been clicked helped greatly - the selector was UUUUGGGGLLLYYYY though.

.class1.class2 .class3:hover > button:not([attrName="true") ~ ul.class4
2 Likes