The cited solution appears a little buggy, as it replaces all potentially existing classes of the menu items. But what makes it not suitable for your use case is, that it is intended to add the active
class only, if the current path matches the menu link's URL path.
What you are looking for instead, is the menu items' "active trail". It is a flag set by the menu module on every menu item found when traversing the menu tree upwards, starting from the current active item up to the menu root.
With this information at hand, have a check for the default menu template. It features the menu item specific property in_active_trail
:
in_active_trail: TRUE if the link is in the active trail.
So you can easily add the active
class to your currently active menu item and all its parents by using the following in your theme's menu.html.twig
:
{%
set link_classes = [
item.in_active_trail ? 'active',
]
%}
{{ link(item.title, item.url, {'class': link_classes}) }}
A more complete example for a Bootstrap 4 navigation with menu.html.twig
:
{#
/**
* @file
* Theme override to display a Bootstrap 4 menu.
*/
#}
{% import _self as menus %}
{{ menus.menu_links(items, attributes, 0) }}
{% macro menu_links(items, attributes, menu_level) %}
{% import _self as menus %}
{% if items %}
{% if menu_level == 0 %}
<ul{{ attributes.addClass('nav') }}>
{% else %}
<ul class="menu">
{% endif %}
{% for item in items %}
{%
set classes = [
'nav-item',
item.is_expanded ? 'menu-item--expanded',
item.is_collapsed ? 'menu-item--collapsed',
item.in_active_trail ? 'menu-item--active-trail',
]
%}
<li{{ item.attributes.addClass(classes) }}>
{%
set link_classes = [
'nav-link',
item.in_active_trail ? 'active',
]
%}
{{ link(item.title, item.url, {'class': link_classes}) }}
{% if item.below %}
{{ menus.menu_links(item.below, attributes, menu_level + 1) }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}