Drupal Menus and Navigation — Building Navigation Systems
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]
Menu System Overview
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'
Adding Menu Links
Navigate to Structure > Menus > Add link.
Menu Link Configuration
# 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
Adding Links from Content
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
Menu Hierarchy
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)
Menu Blocks
Menus are displayed on the page as blocks.
Placing a Menu Block
- Navigate to Structure > Block layout
- Click "Place block" in the desired region
- Search for your menu block (e.g., "Main navigation")
- 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
Menu Block Display Levels
# 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
Breadcrumb Configuration
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,
];
}
}
Breadcrumb Template
{# 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 Link Content Entity
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();
Menu Theming
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>
Menu Item Attributes
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
- 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.
- 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.
- 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.
- Ignoring Accessibility: Screen readers need proper ARIA labels, focus management, and keyboard navigation. Test menus with keyboard-only navigation.
- Not clearing cache after menu changes: Menu changes may not appear immediately due to Caching. Run
drush crafter significant menu modifications.
Practice Questions
- What are the five default menus provided by Drupal and what is each one used for?
- How would you create a menu hierarchy three levels deep and display only the second and third levels in a sidebar block?
- How does taxonomy menu integration work, and what are the benefits of using taxonomy-driven menus instead of manually creating menu links?
- 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
Mini Project
Goal: Build a complete navigation system for a multi-section corporate website.
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
- About Us (parent)
Create a Footer menu with:
- Privacy Policy
- Terms of Service
- Accessibility
- Sitemap
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)
Configure breadcrumbs to show the full path: Home > Services > Consulting
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.twigwith dropdown support
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