I'm trying to create a left sidebar vertical menu block, that will open up to display 2nd-level menu items on a hover or click. The dropdown style does that, but displays the menu items with "nowrap" by default, which is problematic for sidebars (it doesn't increase the container width, it just runs over the right edge). The hierarchical tree style is confusing, it says "Blocks that start with the 2nd level or deeper will only be visible when the trail to the active menu item passes though the block’s starting level." but in fact displays all menu items up to the Maximum depth, always.

Is this something I need Nice Menus or some such to do? It seems like a pretty normal navigation style. Maybe it's outdated?

Comments

This definitely seems like a common use-case, but in practice is a little tricky.

I took a look at the Nice Menus module to see if it would meet your case, but it doesn't appear to. It provides a few options for fancy expandable menus, but they are more complicated than just opening or closing the sub-menu. Here is a screenshot from the Nice Menus module, set to use the "right" style of menu expanding:

nice menu style "right"
Nice Menu style "right"

The module doesn't appear to be responsive, so on mobile devices this menu becomes completely unusable.

Specifically what you asked for was "display 2nd-level menu items on a hover or click", and those are separate, but similar, conflicting use-cases. Consider this: what if your top-level menu items are links themselves? Then if you click on a top-level menu item, should that click send the user to the link, or should it expand the sub-menu items? You can't do both.

Additionally, consider that someone can't "hover" on a mobile device.

I believe ultimately what you'll want to do is have your top-level items not be links at all, but be containers for sub-menus. That way when someone clicks on those top-level items, then you know that they want to open the sub-menu as opposed to visit a link.

One way to achieve this is to add some javascript to your site that will handle the opening and closing of sub-menus when a top-level item is clicked. It's hard to provide the perfect code for every site, but here is an example.

<script>
var $block_menus = $('.block-content > .menu-tree .has-children');
$block_menus.find('ul').hide()
$block_menus.find('> a').click(function(e) {
  e.preventDefault();
  // close all open sub-menus
  $(this).closest('ul').find('ul').hide();
  // open the sub-menu for the item clicked.
  $(this).siblings('ul').show();
});
</script>

If you are familiar with modifying theme code, they you should be able to put this in the right place in your theme.

If you're not familiar with modifying your theme, then the easiest way to add this to your site would be to create a custom block on your site with this code as the block content (set the format to Full HTML), then place that block in the footer of your layouts.

Again, this isn't the perfect solution to a complex problem, I just wanted to provide somethings to think about, and maybe a little direction.

Here is a screenshot of my custom block:

Here is a screenshot of how I've placed it in the footer of a layout:

And here is a gif of this exact code working on my test site:

I had thought this was a default feature in Drupal 8, for instance, but it turns out to be provided by the Bootstrap theme instead. Drupal 7 does seem to require custom code of some kind, like what you're suggesting. So I guess it's not as common as I thought, just an accident of the examples in my experience.

The Bootstrap code makes parent links only open up to display children when clicked, on desktop or mobile, so that seems to likely be the model to emulate.

The hierarchical tree results still seem like either a bug or a need for better wording to describe what it's supposed to do.

Olafski's picture

I'd recommend the dropdown style even if it displays the menu items with "nowrap" by default, so that long items run over the right edge. Problematic in this case, but easy to change by overwriting the CSS, for instance this way:

@media (min-width: 48em) {
  .l-sidebar .menu-dropdown a {
    white-space: unset;
  }
}

To overwrite CSS, you could create a subtheme or use a module like CSS Injector.

The menu creation would certainly be more convenient without the need to overwrite CSS. Actually, out of the box all the menu styles don't look good in the sidebar. That's fine for me because I tend to adapt the menu CSS anyway. On the other hand, the dropdown style looks even broken in a sidebar because the list items are floating left.

I guess it makes sense to suggest some improvements regarding sidebar menus in the Backdrop core queue.

edit: I've made two suggestions in the core queue: https://github.com/backdrop/backdrop-issues/issues/3400