How to Add Nested Navigation to Shopify Themes

Keir Whitaker By Keir Whitaker  |  Jun. 25, 2014

In this article we will discuss how to implement a fully content managed multi-level navigation system within a Shopify theme.

Shopify themes use Liquid, a flexible and powerful template language, to output data from a store into a template. If you aren’t familiar with Liquid, and Shopify theme building in general then I recommend checking out the official Shopify theme documentation.


Getting started

If you have ever worked with platforms like WordPress you might be familiar with admin interfaces that allow you to create multi level navigation. When output in a template file these often result in a nested unordered list which, using CSS, we can style into a variety of design patterns. For example a drop down menu or a sidebar menu that reveals more detailed filtering when the top level menus are clicked or hovered over. All approaches give us the ability to offer deeper navigation into our sites without too much complication.


On first inspecting the navigation function in Shopify you might think that it doesn’t offer us this capability. However armed with a little Liquid knowledge we can take easily achieve multi-level menus in our themes. By using the navigation functionality we can offer our clients an easy way to manage their menus whilst giving us, as theme designers, the desired nested unordered lists for CSS styling.

Our aim in this tutorial is to create a nested unordered list which we can fully control from within the Shopify admin area and for these changes to be reflected in our store.

And here’s the end result:

<li><a href="/">Home</a></li>
<li><a href="/collections/cups">Coffee Cups</a>
<li><a href="/products/edible-coffee-cup">Edible Coffee Cup</a></li>
<li><a href="/products/moustache-mug">Moustache Mug</a></li>
<li><a href="/collections/all">All Products</a></li>
<li><a href="/pages/about">About</a></li>
<li><a href="/blogs/news">Blog</a></li>

Unlike other platforms Shopify doesn’t have the option of having one “super menu” which we can nest our sub-menu items in. That said it’s not a complicated procedure to get this working. By following a simple naming convention it’s possible to generate multi level menu structures.

If you wish to code along with the tutorial the simplest way to do so is to sign up for a free Shopify Partner account and create a free “dev shop”. These are fully featured and allow you to try out your theme before handing it over to your client or launching your own store.

You can try out the code examples in any of the templates in your themes “templates” theme folder, or alternatively I would recommend using the themes default layout file theme.liquid as this will mean your code will appear by default on every page.


Creating menus

Let’s begin by creating a new menu, our parent menu, by heading to the Navigation tab in the Shopify admin. In order to create a menu we need to open up the Shopify admin interface and head to the “Navigation” tab on the left hand side.

All stores have a predefined default menu called “Main Menu”. To add items to the list simply click the “add another link” button and give your new item a “link name” and a destination. The select drop down will allow you to easily link to internal sections such as a particular product or collection. Alternatively you can enter your own URL (either internal or external) by choosing “web address” from the options.


It’s easy to create and edit menus in the Shopify admin.

Once we have this in place we can start to consider the Liquid code we will need to output this in our theme.

In order to output the menu in our theme file we’ll need to know the “handle” of the menu. Handles are unique identifiers within Shopify for products, collections, link lists (the term used for menus in Shopify themes) and pages. They are generally URL safe versions of the name or title of the item. For example Main Menu would result in a handle of main-menu. Whilst they are auto generated you can change them should you wish via the admin interface.


Our default main menu features a link to the Coffee Cups collection.


Single level navigation

Let’s start by outputting all the items from our “main menu”. In order to do this we can use a simple “for loop” to output all the link list items in turn, here’s how:

{% for link in linklists.main-menu.links %}
<li><a href="{{ link.url | escape }}">{{ link.title | escape }}</a></li>
{% endfor %}

Let’s have a look at this in more detail. After opening our <ul> we start our Liquid “for loop”. This will output every item contained in the “main-menu” link list. The syntax is a little long here but all we are really doing is assigning the properties of each item in our link list to the variable link. Using this variable we can access the properties of our menu items, in this case url and title.

In order to output the URL and title properties we use the Liquid output syntax of double curly braces, e.g {{ }}. In our example above {{ link.url }} will output the url we entered or generated in the admin and {{ link.title }} will output the text we attributed to the link.

You will have probably noticed the | escape section of code which I haven’t explained. This is a Liquid filter. A filter is a function that changes the input value in a certain way. By way of an example let’s look at the upcase filter:

{{ 'Keir Whitaker' | upcase }}

When output this will render KEIR WHITAKER in our HTML file.

Filters take an input, in this example my name as a text string and change it accordingly. In the case of the upcase filter it transforms the output into uppercase characters. In our example above the escape filter takes the input of URL and title and escapes the text and URL so they are output correctly.


Multi level navigation

Now we have the basics under our control we need a way of creating a relationship to our secondary sub-menu. Luckily this isn’t that hard, it just takes a couple more lines of Liquid code. Firstly we need to head back to the Shopify admin and create our sub menu.

We need a way of relating our two menus so our template knows how to output them. Handles come to our rescue once again. It’s not 100% clear initially but every link in addition to the menu itself has a unique handle that we have access to.

Let’s have a look at an example by creating a sub menu from our “Coffee Cups” link. We can safely assume our menu item called “Coffee Cups” auto generated handle will be “coffee-cups”. All you really need to do is remove any punctuation, replace uppercase characters with lowercase and spaces with dashes. If we would like this menu item to have a sub menu we simply make sure that our sub menu also has a handle of “coffee-cups”. It’s worth noting that the title of your menu can be anything, the important factor here is the handle.


Our sub menu has a handle of coffee-cups allowing us to relate our menus together.


Now all we need is a little extra Liquid code to help us output the sub menu in our template:

{% for link in linklists.main-menu.links %}
<li><a href="{{ link.url| escape }}">{{ link.title | escape }}</a>
{% if linklists[link.handle].links.size > 0 %}
{% for sublink in linklists.[link.handle].links %}
<li><a href="{{ sublink.url }}">{{ sublink.title | escape }}</a></li>
{% endfor %}
{% endif %} 
{% endfor %}

On first inspection this might be a little daunting. We’ve gone over the majority of it already so let’s examine the new code that’s doing the bulk of the new work for us:

{% if linklists[link.handle].links.size > 0 %}

This appears after the parent menu link is output but before the list items closing </li> tag (line 4 in our code example). The “if statement” checks to see if there is a link list with the same handle as our current link item and if it does exist to see if it has any link items associated with it. If the answer is yes the template opens up a new unordered list and outputs each sub menu item as a list item as per our first example. If the answer is no then the template carries on outputting the next parent menu item.


The end result of our code is a nested unordered list of menu items.


This check for the existence of a sub menu with the same handle occurs on each and every iteration of the parent menu. You’ll also notice that our “if statement” is closed off with the Liquid code {% end for %} and our “for loop” with {% end for %}. This alerts the template to move on when these have completed their work.


Wrapping up

With a little planning it’s actually very easy to create menus that are dependant on each other. Of course you don’t have to output them together – you could if you wish output the sub menu independently anywhere in your template.

I hope this has given you an insight into how easy it is to create versatile menu systems in Shopify themes.