Menus and Navigation

Last updated:

Almost all websites have some form of a navigation menu to help users find information quickly and easily. Navigation menus are often located in the headers, sidebars, and footers of a website. Because they are so common, HubSpot has a few built-in tools to make the creation and management of these menus easy, and on the code side multiple solutions for displaying menus so you can pick the solution that makes the most sense for your website.

For menus that are used globally throughout a site, like a site's header or footer menu there is a navigation settings page. In this screen, you create, update, and delete menus, which can be used by any templates or modules in your account. HubSpot provides a menu module and tag to make displaying the menu on your site easy.

For menus that may only make sense for a single page, like a pillar page's table of contents, there are simple menus. Simple menus are not global and are specific to the page they are displayed on(unless included in global content). Simple menus are editable at the page level by content editors and provide a similar UI for creating/managing them. HubSpot provides a simple menu module and tag to make displaying a simple menu on your site easy.

Custom modules can have both simple menu and menu fields.  Because developers have more control over the output code, custom modules are generally the preferred method for most developers. Enabling you to create sidebar modules, footer nav modules, header nav modules, etc to fit your workflow and business or design needs. Menu fields enable the content editor to pick a menu from the global account navigation menus. The simple menu field enables them to create menus that are not reusable elsewhere.

For truly complicated menu use-cases it may make sense to use a module with repeater groups or a HubDB to manage the structure and way the menu takes shape. That said that method comes at the cost of an easy UI for content editors. For situations like that it may make sense to use menu or simple menu fields in tandem with the menu function, to make it so you can provide advanced structure, functionality, AND a good menu experience.

Custom menu options

Most website menus follow a similar format and the HubSpot CMS provides a useful editor UI to facilitate menu creation in that parent-child format. This user interface (UI) allows you to nest links to pages under each other to create multi-level menus. Menus created here can be displayed in any type of template, or module. To configure account-wide menu's head to Settings > Pages > Navigation.

Navigation settings area

A HubSpot account can have multiple menus, you can use these for your main navigation, sidebars, mega-menus, footer navs, etc. Menus defined in the navigation settings are re-usable throughout a website.

Displaying Menus

There are multiple ways of displaying menus. You should determine which of the following makes the most sense for your use-case.

Each come with their advantages and disadvantages, make sure you understand them before you decide.

As a friendly reminder: A best practice for site headers which often contain the lengthy main navigation - is to provide a "skip to content" link. This helps users navigating by keyboard, skip over lengthy menus.

Get Your Menu ID

When working with menus in HubL you need to use the menu's ID to reference it. This does not apply to simple menus.

If you're building a custom module the best way to get the menu id, is actually to create a menu field. The menu field in a module returns the menu's id giving the content editor a way to pick the menu. If for some reason you want or need to hard code the menu id, you can get the menu id from the URL when viewing the navigation settings page.

https://app.hubspot.com/menus/<portal id>/edit/<menu id>

The default menu doesn't always display the id out-right, change menus then change to the default, to cause the id to show in the URL.

The HubL Menu Tag

The HubL Menu tag generates standard menu HTML with class names already provided for depth levels, active states, and if the item has children. The menu tag can be used within custom modules making it an easy way to create navigation menus for main nav's and sidebar navigation. This tag expects you to provide the menu id. Since this is a HubL tag and not a module it can be used within custom modules.

HubL
{% menu "menu" %}
{% menu "my_menu" id=456, site_map_name='Default', overrideable=False, root_type='site_root', flyouts='true', max_levels='2', flow='horizontal', label='Advanced Menu' %}

The HubL Simple Menu Tag

Similar to the HubL Menu tag, the simple menu tag functions just like the HubL menu tag generating standard menu HTML with class names for depth levels, active states, and if the item has children. The difference is that this tag expects you to provide a dict of the menu structure instead of a menu ID. This is good for when you want a module's fields to determine the structure of a menu instead of using the navigation settings. A scenario where you may want this is for a table of contents type menu for a long page. That menu wouldn't be repeated on other pages, so it's okay that it's not in the navigation settings. Because this is a HubL tag, and not a module it can be used within custom modules.

HubL
{% simple_menu menu_tree=[{"contentType": null, "subCategory": null, "pageLinkName": null, "pageLinkId": null, "isPublished": false, "categoryId": null, "linkParams": null, "linkLabel": "Home", "linkTarget": null, "linkUrl": "http://www.hubspot.com", "children": [], "isDeleted": false}, {"contentType": null, "subCategory": null, "pageLinkName": null, "pageLinkId": null, "isPublished": false, "categoryId": null, "linkParams": null, "linkLabel": "About", "linkTarget": null, "linkUrl": "http://www.hubspot.com/internet-marketing-company", "children": [{"contentType": null, "subCategory": null, "pageLinkName": null, "linkUrl": "http://www.hubspot.com/company/management", "isPublished": false, "children": [], "linkParams": null, "linkLabel": "Our Team", "linkTarget": null, "pageLinkId": null, "categoryId": null, "isDeleted": false}], "isDeleted": false}, {"contentType": null, "subCategory": null, "pageLinkName": null, "pageLinkId": null, "isPublished": false, "categoryId": null, "linkParams": null, "linkLabel": "Pricing", "linkTarget": null, "linkUrl": "http://www.hubspot.com/pricing", "children": [], "isDeleted": false}]

The Default Menu Modules

We provide default modules that can be used in both HTML+HubL and Drag and Drop templates. The default menu module under the hood uses the HubL menu tag. The default simple menu module under the hood uses the HubL simple_menu tag. Since they use the HubL menu tags, it generates standard menu HTML. Because these are actual modules, you can use them within dnd_area tags, flexible columns and drag and drop templates. Because modules cannot be nested you cannot place these modules inside of other modules. Instead, you should use the menu or simple menu tags.

HubL
{% module "main_nav" path="@hubspot/menu", label="Menu" id="123456" %}

{% module "menu" path="@hubspot/simple_menu", label="Simple Menu" menu_tree=[{"contentType": null, "subCategory": null, "pageLinkName": null, "pageLinkId": null, "isPublished": false, "categoryId": null, "linkParams": null, "linkLabel": "Home", "linkTarget": null, "linkUrl": "http://www.hubspot.com", "children": [], "isDeleted": false}, {"contentType": null, "subCategory": null, "pageLinkName": null, "pageLinkId": null, "isPublished": false, "categoryId": null, "linkParams": null, "linkLabel": "About", "linkTarget": null, "linkUrl": "http://www.hubspot.com/internet-marketing-company", "children": [{"contentType": null, "subCategory": null, "pageLinkName": null, "linkUrl": "http://www.hubspot.com/company/management", "isPublished": false, "children": [], "linkParams": null, "linkLabel": "Our Team", "linkTarget": null, "pageLinkId": null, "categoryId": null, "isDeleted": false}], "isDeleted": false}, {"contentType": null, "subCategory": null, "pageLinkName": null, "pageLinkId": null, "isPublished": false, "categoryId": null, "linkParams": null, "linkLabel": "Pricing", "linkTarget": null, "linkUrl": "http://www.hubspot.com/pricing", "children": [], "isDeleted": false}] %}

A custom-built menu using the menu() function

The menu() function exists to enable you to create fully custom menu structures. It returns an object that you can iterate through to generate a menu, there are many provided properties for the menu items. Be aware when you use the menu function you are fully responsible for the accessibility of your menu, the structure, and the styling.

The HubSpot CMS Theme Boilerplate contains an example menu module built with the menu() function. You can modify that to meet your needs to make complicated menus like mega-menus.