Skip to main content
Timber

You are reading the documentation for Timber v1.x. Switch to the documentation for Timber v2.x.

Menus

In Timber, you can use Timber\Menu to make a standard WordPress menu available to the Twig template as an object you can loop through.

Once the menu becomes available to the context, you can get items from it in a way that is a little smoother and more versatile than WordPress’s wp_nav_menu() function. (And you never again need to rely on a crazy Walker Function).

Initializing a menu #

Timber\Menu can be initialized with different values:

You can pass the slug of the menu you want to use:

$menu = new Timber\Menu( 'site-tools' );

Or the ID number of the menu:

$menu = new Timber\Menu( 3 );

Or the proper name from the admin:

$menu = new Timber\Menu( 'Primary Navigation' );

Or the slug of the registered location:

$menu = new Timber\Menu( 'primary' );

Or pass nothing. This is good if you have only one menu. In that case Timber will just grab what you got.

$menu = new Timber\Menu();

Options #

Optionally, you can send additional options to Timber\Menu. Current only depth is supported (see https://developer.wordpress.org/reference/functions/wp_nav_menu/ for reference)

$args = array(
'depth' => 2,
);
$menu = new Timber\Menu( 'primary', $args );

Setting up a menu globally #

The first thing to do is to initialize your menu using Timber\Menu. This will make the menu available as an object to work with in the context. Because we need the menu on every page, we can add it to the global context through the timber/context filter:

functions.php

<?php

add_filter( 'timber/context', 'add_to_context' );

function add_to_context( $context ) {
// So here you are adding data to Timber's context object, i.e...
$context['foo'] = 'I am some other typical value set in your functions.php file, unrelated to the menu';

// Now, in similar fashion, you add a Timber Menu and send it along to the context.
$context['menu'] = new \Timber\Menu( 'primary-menu' );

return $context;
}

Now, when you call Timber::context(), your menu will already be set in the context. You don’t need to initialize the menu in all your template files.

index.php

<?php

$context = Timber::context();

Timber::render( 'index.twig', $context );

When adding multiple menus to the global $context, declare unique names for each menu in the add_to_context function.

functions.php

public function add_to_context( $context ) {
$context['primary_menu'] = new Timber\Menu('Primary Navigation');
$context['footer_menu'] = new Timber\Menu('Footer Navigation');
// ...
return $context;
}

Displaying the menu items #

In your Twig file, you can loop over the menu items like normal arrays. You’re in complete control of the markup.

index.twig

<nav>
<ul class="nav-main">
{% for item in menu.items %}
<li class="nav-main-item {{ item.classes|join(' ') }}">
<a class="nav-main-link" href="{{ item.link }}">{{ item.title }}</a>
{% if item.children %}
<ul class="nav-drop">
{% for child in item.children %}
<li class="nav-drop-item">
<a href="{{ child.link }}">{{ child.title }}</a>
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
</nav>

When using multiple menus, use the unique name in your Twig markup. Notice primary_menu.items instead of menu.items.

index.twig

<nav>
<ul class="nav-main">
{% for item in primary_menu.items %}
<li class="nav-main-item {{ item.classes|join(' ') }}">
<a class="nav-main-link" href="{{ item.link }}">{{ item.title }}</a>
<!-- ... -->
</li>
{% endfor %}
</ul>
</nav>

The current menu item #

When you need to check whether a menu item is the current menu item, you can use the current property. Here’s an example to display child menu items only if it’s the menu item is the currently visited page:

Twig

{% if item.current and item.children %}
<ul class="nav-child">
{% for child in item.children %}
<li class="nav-child-item">
<a class="nav-child-link" href="{{ child.link }}">{{ child.title }}</a>
</li>
{% endfor %}
</ul>
{% endif %}

Other properties that are available are current_item_parent for direct parents of a menu item and current_item_ancestor for when you have deeper nesting.

Tips #