Skip to content

Drupal Menus and Navigation — Building Navigation Systems

DodaTech Updated 2026-06-27 10 min read

In this tutorial, you'll learn Drupal menus including built-in menu types, creating and managing menu links, building hierarchical menus, configuring menu blocks, breadcrumb navigation, and implementing taxonomy-driven navigation and megamenus.

What You'll Learn

  • Drupal's built-in menus: Main navigation, Footer, Tools, Account menu, Admin menu
  • Creating new menus and adding menu links
  • Building menu hierarchies with parent/child relationships
  • Displaying menus as blocks in theme regions
  • Configuring breadcrumb navigation
  • Creating megamenus using contributed modules
  • Taxonomy-based menus for content-driven navigation
  • Menu theming with Twig templates

Why It Matters

Navigation is the primary way users interact with your website. Well-designed menus reduce bounce rates, improve task completion, and boost SEO through clear site architecture. Drupal's menu system supports unlimited hierarchical depth, integration with content and taxonomy, and flexible display through blocks and theming, making it suitable for sites from five pages to fifty thousand.

Real-World Use

An e-commerce site with 500 product categories organizes navigation using taxonomy menus. The main navigation shows top-level departments (Electronics, Clothing, Home & Garden). Each department expands to show subcategories (Electronics > Computers > Laptops, Desktops, Tablets). When a new product category is added to the taxonomy, the menu updates automatically. Breadcrumbs show the full path: Home > Electronics > Computers > Laptops.

Learning Path

flowchart LR
  A[Blocks] --> B[Menus & Navigation]
  B --> C[Layout Builder]
  C --> D[Next: Custom Modules]

Drupal provides several default menus:

Menu Machine Name Purpose
Main navigation main Primary site navigation
Footer footer Footer links
Tools tools User tools (deprecated in Drupal 10)
Account menu account Login, My account, Log out
Administration admin Admin dashboard navigation

Creating a Menu

Navigate to Structure > Menus > Add menu (or /admin/structure/menu/add).

# New menu configuration
Title: Services
Machine name: services
Description: 'Services navigation menu'

Navigate to Structure > Menus > Add link.

# Menu link settings
Menu link title: About Us
Path: /about
Description: 'Learn about our company history and team'
Enabled: true
Show as expanded: false
Parent link: <Main navigation>
Weight: 0

Internal Paths

# Internal path examples
Path: /node/42              # Specific content item
Path: /taxonomy/term/5      # Taxonomy term page
Path: /user/login           # Login page
Path: /<front>              # Front page
Path: /contact              # Contact form

External Paths

# External path
Title: Drupal.org
Path: https://www.drupal.org

While editing content, use the "Menu settings" section to add a menu link directly:

Content: Article
Menu settings:
  Provide a menu link: true
  Menu link title: 'Our Latest Article'
  Parent item: <Main navigation>
  Weight: 0

Menus support unlimited depth of parent/child relationships.

Building Hierarchy

Main navigation
├── About
│   ├── Our Team
│   ├── History
│   └── Careers
│       ├── Open Positions
│       └── Benefits
├── Services
│   ├── Consulting
│   ├── Development
│   └── Support
└── Contact

Drag and Drop Ordering

On the menu edit page, use the drag handles to reorder links and adjust hierarchy.

# Weight-based ordering
Parent: About (weight: 0)
  - Our Team (weight: 0)
  - History (weight: 1)
  - Careers (weight: 2)
    - Open Positions (weight: 0)
    - Benefits (weight: 1)
Parent: Services (weight: 1)

Menus are displayed on the page as blocks.

Placing a Menu Block

  1. Navigate to Structure > Block layout
  2. Click "Place block" in the desired region
  3. Search for your menu block (e.g., "Main navigation")
  4. Configure block settings:
# Menu block configuration
Block: Main navigation
Display title: false
Region: Header
Visibility:
  Path:
    - /services/*

Block settings:
  Starting level: 1
  Maximum depth: 3
  Expand all items: false
# Show full menu from top level
Starting level: 1
Maximum depth: 0  (unlimited)

# Show only second level (children of current page)
Starting level: 2
Maximum depth: 3

Breadcrumbs show the user's current location in the site hierarchy.

Enabling Breadcrumbs

Breadcrumbs are enabled by default in Olivero theme. They appear as a system block.

Configuring Trails

Drupal automatically generates breadcrumbs based on menu hierarchy:

Home > About > Our Team
Home > Services > Consulting
Home > Blog > Article Title

Custom Breadcrumbs via Theme

<?php

// theme.theme file
function mytheme_preprocess_breadcrumb(&$variables) {
  $trail = &$variables['breadcrumb'];
  $current_path = \Drupal::service('path.current')->getPath();

  if ($current_path === '/node/42') {
    $trail[] = [
      'text' => 'Custom Page',
      'url' => NULL,
    ];
  }
}
{# templates/system/breadcrumb.html.twig #}
<nav role="navigation" aria-labelledby="breadcrumb-label">
  <h2 id="breadcrumb-label" class="visually-hidden">Breadcrumb</h2>
  <ol class="breadcrumb">
    {% for item in breadcrumb %}
      <li class="breadcrumb__item">
        {% if item.url %}
          <a href="{{ item.url }}" class="breadcrumb__link">{{ item.text }}</a>
        {% else %}
          <span class="breadcrumb__current">{{ item.text }}</span>
        {% endif %}
      </li>
    {% endfor %}
  </ol>
</nav>

Creating Megamenus

Megamenus are wide dropdown menus showing multiple columns of links, images, and content.

Using Menu Block Module

The contributed Menu Block module provides advanced menu display options.

# Menu Block configuration for megamenu
Menu: Main navigation
Display style: Dropdown
Levels: 3
Depth: 3
Show children of active trail only: false

Superfish Module

The Superfish module creates responsive dropdown menus.

composer require drupal/superfish
# Superfish configuration
Superfish block: Main navigation
Style: Default
Animation: fade
Speed: 200
Delay: 300

Custom Megamenu via Twig

{# templates/menu/menu--main.html.twig #}
<nav class="megamenu">
  <ul class="megamenu__list">
    {% for item in items %}
      <li class="megamenu__item{{ item.below ? ' megamenu__item--has-children' : '' }}">
        <a href="{{ item.url }}" class="megamenu__link">{{ item.title }}</a>
        {% if item.below %}
          <div class="megamenu__dropdown">
            <ul class="megamenu__sublist">
              {% for subitem in item.below %}
                <li class="megamenu__subitem">
                  <a href="{{ subitem.url }}" class="megamenu__sublink">{{ subitem.title }}</a>
                  {% if subitem.below %}
                    <ul class="megamenu__subsublist">
                      {% for subsubitem in subitem.below %}
                        <li>
                          <a href="{{ subsubitem.url }}">{{ subsubitem.title }}</a>
                        </li>
                      {% endfor %}
                    </ul>
                  {% endif %}
                </li>
              {% endfor %}
            </ul>
          </div>
        {% endif %}
      </li>
    {% endfor %}
  </ul>
</nav>

Taxonomy Menus

Taxonomy-driven navigation creates menus that automatically update when taxonomy terms change.

Using Taxonomy Menu Module

The contributed Taxonomy Menu module creates menu links from taxonomy terms.

composer require drupal/taxonomy_menu
# Taxonomy menu configuration
Taxonomy vocabulary: Product categories
Menu: Main navigation
Menu hierarchy matches taxonomy hierarchy: true

When a new term is added to the "Product categories" vocabulary, a corresponding menu link is automatically created in the Main navigation menu.

Menu links are content entities (menu_link_content) that can be created and managed programmatically.

<?php

use Drupal\menu_link_content\Entity\MenuLinkContent;

// Create a menu link programmatically
$menu_link = MenuLinkContent::create([
  'title' => 'New Services Page',
  'link' => [
    'uri' => 'internal:/services/new',
    'options' => [
      'attributes' => [
        'class' => ['services-link'],
        'target' => '_blank',
      ],
    ],
  ],
  'menu_name' => 'main',
  'parent' => 'menu_link_content:abc123',  // parent link UUID
  'weight' => 10,
  'expanded' => true,
  'enabled' => true,
]);
$menu_link->save();

// Load existing menu link
$menu_link = \Drupal::entityTypeManager()
  ->getStorage('menu_link_content')
  ->load(5);

// Update menu link
$menu_link->set('title', 'Updated Services Page');
$menu_link->save();

// Delete menu link
$menu_link->delete();

Template Suggestions

{# Base menu template #}
menu.html.twig

{# Specific menu #}
menu--main.html.twig
menu--footer.html.twig

{# Menu by region #}
menu--region-header.html.twig
menu--region-footer.html.twig

Example Menu Template

{# templates/menu/menu--footer.html.twig #}
<nav class="footer-nav" role="navigation">
  <ul class="footer-nav__list">
    {% for item in items %}
      <li class="footer-nav__item{{ item.below ? ' footer-nav__item--has-children' : '' }}">
        <a href="{{ item.url }}" class="footer-nav__link">
          {% if item.below %}
            <span class="footer-nav__label">{{ item.title }}</span>
          {% else %}
            {{ item.title }}
          {% endif %}
        </a>
        {% if item.below %}
          <ul class="footer-nav__sublist">
            {% for subitem in item.below %}
              <li class="footer-nav__subitem">
                <a href="{{ subitem.url }}" class="footer-nav__sublink">{{ subitem.title }}</a>
              </li>
            {% endfor %}
          </ul>
        {% endif %}
      </li>
    {% endfor %}
  </ul>
</nav>

Add HTML attributes to menu links for CSS styling and JavaScript behavior.

# Menu link with attributes
Title: External Link
Path: https://example.com
Attributes:
  class: ['external-link', 'highlight']
  target: '_blank'
  rel: 'noopener noreferrer'

Common Mistakes

  1. Creating menus that are too deep: More than three levels of navigation creates usability issues. If you need more depth, consider sidebar navigation or faceted search instead.
  2. Not using "Show as expanded" for parent items: Parent menu items with children will not show a dropdown unless "Show as expanded" is checked. Always enable this for parent items.
  3. Hard-coding paths in menus that may change: If you have a "Services" page that might move, use a dynamic path reference. Menu links to deleted nodes produce 404 errors.
  4. Ignoring Accessibility: Screen readers need proper ARIA labels, focus management, and keyboard navigation. Test menus with keyboard-only navigation.
  5. Not clearing cache after menu changes: Menu changes may not appear immediately due to Caching. Run drush cr after significant menu modifications.

Practice Questions

  1. What are the five default menus provided by Drupal and what is each one used for?
  2. How would you create a menu hierarchy three levels deep and display only the second and third levels in a sidebar block?
  3. How does taxonomy menu integration work, and what are the benefits of using taxonomy-driven menus instead of manually creating menu links?
  4. Challenge: Build a complete navigation system for a large e-commerce site. Create a "Product Categories" taxonomy with four levels of hierarchy (Department > Category > Subcategory > Type). Use Taxonomy Menu to automatically sync the taxonomy to the Main navigation. Create a megamenu using the Menu Block module or custom Twig that shows the first three levels of categories with category images. Configure breadcrumbs using the Product Categories taxonomy hierarchy. Create footer menus for Support, Company, and Legal. Set up a "Secondary navigation" menu block on category pages showing only sibling and child categories of the current page.

FAQ

How many levels of menu hierarchy does Drupal support?

Drupal supports unlimited menu levels. However, for usability, most sites use 2-3 levels in the main navigation and reserve deeper levels for sidebar or footer navigation.

Can I have multiple menus on a single page?

Yes. Each menu can be placed as a separate block in different regions. For example, Main navigation in the header, Footer menu in the footer, and a Sidebar menu in the sidebar.

How do I add a menu link to a specific content item?

While editing the content, expand the 'Menu settings' section, check 'Provide a menu link', enter the link title, and select the parent menu. Alternatively, use Structure > Menus > Add link and enter the content's internal path.

What happens to menu links when a referenced node is deleted?

The menu link remains but becomes a broken link pointing to a 404 page. You must manually remove or update the menu link after deleting the referenced content. Enable the Automatic Menu Link module to optionally auto-remove links.

Can I style each menu item individually?

Yes. When creating or editing a menu link, you can add CSS classes through the 'Attributes' fieldset. These classes are rendered in the attributes array available in Twig menu templates.

Mini Project

Goal: Build a complete navigation system for a multi-section corporate website.

  1. Create a Main navigation menu with:

    • About Us (parent)
      • Our Team
      • History
      • Careers
    • Services (parent)
      • Consulting
      • Development
      • Training
    • Resources (parent)
      • Blog
      • Case Studies
      • Whitepapers
    • Contact
  2. Create a Footer menu with:

    • Privacy Policy
    • Terms of Service
    • Accessibility
    • Sitemap
  3. Create a Secondary navigation menu block that shows in the sidebar on all subpages of Services, displaying only sibling pages (e.g., on /services/consulting, show Consulting, Development, Training)

  4. Configure breadcrumbs to show the full path: Home > Services > Consulting

  5. Customize the Main navigation menu block with:

    • "Show as expanded" on all parent items
    • CSS classes on specific items for highlighting
    • Custom Twig template: menu--main.html.twig with dropdown support
  6. Create a programmatic menu link via Drush PHP:

$menu_link = \Drupal\menu_link_content\Entity\MenuLinkContent::create([
  'title' => 'New Page',
  'link' => ['uri' => 'internal:/new-page'],
  'menu_name' => 'main',
  'parent' => 'menu_link_content:uuid-of-services',
  'weight' => 0,
]);
$menu_link->save();

What's Next

Menus guide users through your site, but Layout Builder gives you control over page composition. Learn Drupal Layout Builder for drag-and-drop page layout design without custom code.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro