Dynamic Navigation Menus with Jekyll Data Files

Benefits of Dynamic Navigation Menus

Static navigation menus require manual updates in multiple places when your site structure changes. Dynamic menus built with Jekyll data files and includes:

  • Centralize menu configuration in one place
  • Allow easy addition, removal, or rearrangement of links
  • Enable multi-level nested menus for complex sites
  • Improve maintainability and reduce errors

Setting Up Your Navigation Data File

Create a YAML data file _data/navigation.yml to define your menu structure. Example:


- title: Home
  url: /
- title: About
  url: /about/
- title: Blog
  url: /blog/
  children:
    - title: Tutorials
      url: /blog/tutorials/
    - title: News
      url: /blog/news/
- title: Contact
  url: /contact/

This format supports nested children for dropdown or expandable menus.

Creating a Navigation Include

Create an include file _includes/navigation.html that loops through this data to render the menu:


<nav>
  <ul class="main-menu">
    {% raw %}{% for item in site.data.navigation %}{% endraw %}
      <li class="menu-item"{% raw %} {% if page.url == item.url %}class="active"{% endif %}{% endraw %}>
        <a href="{% raw %}{{ item.url }}{% endraw %}">{% raw %}{{ item.title }}{% endraw %}</a>
        {% raw %}{% if item.children %}{% endraw %}
          <ul class="submenu">
            {% raw %}{% for child in item.children %}{% endraw %}
              <li class="submenu-item"{% raw %} {% if page.url == child.url %}class="active"{% endif %}{% endraw %}>
                <a href="{% raw %}{{ child.url }}{% endraw %}">{% raw %}{{ child.title }}{% endraw %}</a>
              </li>
            {% raw %}{% endfor %}{% endraw %}
          </ul>
        {% raw %}{% endif %}{% endraw %}
      </li>
    {% raw %}{% endfor %}{% endraw %}
  </ul>
</nav>

Including the Navigation in Your Layout

Place the navigation include in your site's layout, for example in _layouts/default.html:

{% raw %}

  {% include navigation.html %}
  
{{ content }}
{% endraw %}

Styling Your Menus

Use CSS to style the main menu and submenu, including hover effects and active states:


.main-menu {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
}
.menu-item {
  position: relative;
  margin-right: 20px;
}
.menu-item a {
  text-decoration: none;
  padding: 10px 15px;
  display: block;
}
.menu-item.active > a {
  font-weight: bold;
  border-bottom: 2px solid #007acc;
}
.submenu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  list-style: none;
  padding: 10px 0;
  background: #fff;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.menu-item:hover .submenu {
  display: block;
}
.submenu-item a {
  padding: 10px 20px;
  display: block;
  white-space: nowrap;
}

Handling Active Menu Highlighting

The include checks if the current page URL matches menu item URLs and applies an active class accordingly. This helps users understand their current location on your site.

Case Study: Simplifying Navigation Updates

A tech blog with dozens of tutorials and categories faced maintenance headaches when updating navigation. By moving menu links into a centralized data file and rendering dynamically, editors could update menus without touching HTML code, reducing errors and speeding up site updates.

Summary

Using Jekyll data files combined with includes for navigation menus greatly enhances flexibility and maintainability. This approach supports nested menus, active state detection, and easier content management.

Next Steps

The next article will explore building multilingual support in Jekyll with data files and Liquid templating for global reach.