Creating nested menus

You can add nested navigation menus to your online store using a new UI and Liquid syntax. The nested navigation feature includes the following:

  • New UI - Merchants can create nested menus up to 3 levels deep from a single page by using the menu editing interface.
  • Backward-compatibility layer - Although menus created with the new UI are stored differently, they work the same way with current Liquid markup.
  • New Liquid markup - You can use simplified Liquid markup including help with styling to render nested menus.

You can start using the new Liquid markup when all stores have been migrated to the new UI. Shopify will notify you when all stores have been migrated.

Backward compatibility with legacy Liquid code

Menus created with the new UI will work with your existing Liquid code. You do not need to make any updates. The number of supported nested menu levels depends on the theme.

How legacy code works with the new UI

When using legacy Liquid markup with the new UI, you can render nested menus by looking up child menus using link titles passed through the handleize filter. Although you must currently manually set up menus that adhere to this naming convention to configure nesting, the new UI handles this transparently in the background.

For example, given the following menu structure:

Main Menu
  └ Home
  └ About Us
    └ Locations
      └ Montreal
      └ Ottawa

the following Liquid code:


{% assign about_us_link = linklists.main-menu.links.last %}
{% assign child_list_handle = about_us_link.title | handleize %}
child_list_handle: {{ child_list_handle }}
{% assign child_list = linklists[child_list_handle] %}
{{ child_list.links.first.title }}

would produce the following output:

child_list_handle: about-us
Locations

New Liquid syntax

You can use the new Liquid syntax after the new UI has been released to all stores.

Instead of relying on {{ child_link.title | handleize }} , nested menu items can be obtained directly from their parent link. This greatly simplifies the markup required to render a nested menu.


<ul>
{% for link in linklists.main-menu.links %}
  <li>
    <a href="{{ link.url }}">{{ link.title | escape }}</a>
    {% if link.links != blank %}
      <ul class="dropdown">
        {% for child_link in link.links %}
          <!-- ... --->

When rendering a menu, it's often helpful to know how many levels of nesting it contains. For example, given the following main menu structure:

Main Menu
  └ Home
  └ About Us
    └ Locations
      └ Montreal
      └ Ottawa

the following Liquid code:


  {% assign menu = linklists.main-menu %}
  <pre>
  {{ menu.title }}: {{ menu.levels }}
  {% for link in menu.links %}
    {{ link.title }}: {{ link.levels }}
    {% for sub_link in link.links %}
      {{ sub_link.title }}: {{ sub_link.levels }}
      {% for sub_sub_link in sub_link.links %}
        {{ sub_sub_link.title }}: {{ sub_sub_link.levels }}
      {% endfor %}
    {% endfor %}
  {% endfor %}
  </pre>

would produce the following output (edited for space):

Main Menu: 3
  Home: 0
  About Us: 2
    Locations: 1
      Montreal: 0
      Ottawa: 0

link.active is often used to style menu items that point to the current page, but there is no easy way of finding out whether any of its nested items point to it as well. link.child_active serves that purpose.

For example, given the following main menu structure:

Main Menu
  └ Home
  └ About Us
    └ In the news
    └ Locations
      └ Montreal
      └ Ottawa

the following Liquid code:


  {% assign menu = linklists.main-menu %}
  <pre>
  {{ menu.title }}
  {% for link in menu.links %}
    {{ link.title }}: active: {{ link.active }}, child_active: {{ link.child_active }}
    {% for sub_link in link.links %}
      {{ sub_link.title }}: active: {{ sub_link.active }}, child_active: {{ sub_link.child_active }}
      {% for sub_sub_link in sub_link.links %}
        {{ sub_sub_link.title }}: active: {{ sub_sub_link.active }}, child_active: {{ sub_sub_link.child_active }}
      {% endfor %}
    {% endfor %}
  {% endfor %}
  </pre>

would produce the following output for the page for Montreal (edited for space):

Main Menu
  Home: active: false, child_active: false
  About Us: active: false, child_active: true
    In the news: active: false, child_active: false
    Locations: active: false, child_active: true
      Montreal: active: true, child_active: false
      Ottawa: active: false, child_active: false

FAQ

  • Will there be an API for menus? Yes, but we can't announce a timeline just yet.
  • Why does it allow only 3 levels of nesting? How do I handle more complex cases? Based on our analysis of themes now in use, we concluded that 3 levels of nesting should cover the vast majority of use cases. More complex scenarios can be handled using the link_list setting type.

Want to discuss this page?

Visit the Shopify Community