Cape Cod, Massachusetts 41°39'20.7"N 70°09'53.0"W
Back to blog Drupal Development

A Bootstrap Navbar in Drupal 8 with four easy template changes

A Bootstrap Navbar in Drupal 8 with four easy template changes

When Drupal 8 landed, I started learning its theming system from scratch, an empty theme folder on top of Stable (core’s base theme at the time). One of the first things I needed was a Bootstrap Navbar that actually worked with Drupal’s menu system. Turns out it’s cleaner than Drupal 7 ever was.

The four templates

You need to override four templates. Create these in your theme’s templates/ folder:

1. html.html.twig

Add the Bootstrap CSS and JS CDN links, and set <html class="no-js"> so Bootstrap’s JavaScript can toggle it to js.

2. page.html.twig

Replace the default page layout with Bootstrap’s container structure. Wrap the header region in a <div class="navbar navbar-default navbar-fixed-top">.

3. menu--main.html.twig

This is where the Bootstrap Navbar classes live. The key is the <ul class="nav navbar-nav"> wrapper around menu items.

{# menu--main.html.twig #}
<ul class="nav navbar-nav">
  {% for item in items %}
    <li{{ item.attributes.addClass(item.is_expanded ? 'dropdown' : '') }}>
      {% if item.is_expanded %}
        <a href="{{ item.url }}" class="dropdown-toggle" data-toggle="dropdown">
          {{ item.title }} <span class="caret"></span>
        </a>
        <ul class="dropdown-menu">
          {% for child in item.below %}
            <li><a href="{{ child.url }}">{{ child.title }}</a></li>
          {% endfor %}
        </ul>
      {% else %}
        <a href="{{ item.url }}">{{ item.title }}</a>
      {% endif %}
    </li>
  {% endfor %}
</ul>

4. block--system-menu-block--main.html.twig

Remove the default block wrapper so the menu renders directly inside your Navbar, without an extra <div> breaking the Bootstrap structure.

What’s easier than D7

In Drupal 7, you needed Menu Block module and often a custom module to manipulate the menu tree. In Drupal 8, Twig templates give you direct access to the menu structure, including the item.below array for submenus, without any additional modules. Four template overrides and you’re done.