This little code snippet will add the present page title to the breadcrumb. We show you how to use this in steps.

Step 1 :

If you do not have

  • Drupal7: a template.php file in your sites/all/themes/yourtheme/
  • Drupal8: a yourtheme.theme in your themes/custom/yourtheme/

folder, create one.

Step 2 :

For Drupal 7

Copy and paste the code in the template.php file.

The function should be.

function MYTHEME_breadcrumb($variables) {
  $breadcrumb = $variables['breadcrumb'];
  if (!empty($breadcrumb)) {
    // Adding the title of the current page to the breadcrumb.
    $breadcrumb[] = drupal_get_title();
    
    // Provide a navigational heading to give context for breadcrumb links to
    // screen-reader users. Make the heading invisible with .element-invisible.
    $output = '<h2 class="element-invisible">' . t('You are here') . '</h2>';

    $output .= '<div class="breadcrumb">' . implode(' » ', $breadcrumb) . '</div>';
    return $output;
  }
}

That's it. Clear your cache. The current node title should now be displayed in the breadcrumb.

Alternative method

Or you can try this alternative solution (no template.php hack required):

<?php if (!drupal_is_front_page()): ?>
<div class="breadcrumb">
<?php print strip_tags($breadcrumb, '<a><h2>') . ' » ' . $title;?>
</div>
<?php endif; ?>

For Drupal 8

The function should be(inside MY_THEME.theme):

use Drupal\Core\Template\Attribute; // this should be at the top of your MY_THEME.theme file

function MYTHEME_preprocess_breadcrumb(&$variables) {
  if ($variables['breadcrumb']) {
    $request = \Drupal::request();
    $route_match = \Drupal::routeMatch();
    $page_title = \Drupal::service('title_resolver')->getTitle($request, $route_match->getRouteObject());
    
    if (!empty($page_title)) {
      $variables['breadcrumb'][] = [
        'text' => $page_title,
        'attributes' => new Attribute(['class' => ['active']])
      ];
    }
  }
}

It is not required to create a new breadcrumb.html.twig template inside your theme for the override to take effect, but make sure that the breadcrumb template used by your theme looks something like the code below:

{% if breadcrumb %}
  <nav class="breadcrumb" role="navigation" aria-labelledby="system-breadcrumb">
    <h2 id="system-breadcrumb" class="visually-hidden">{{ 'Breadcrumb'|t }}</h2>
    <ol>
    {% for item in breadcrumb %}
      <li {{ item.attributes }}>
        {% if item.url %}
          <a href="{{ item.url }}">{{ item.text }}</a>
        {% else %}
          {{ item.text }}
        {% endif %}
      </li>
    {% endfor %}
    </ol>
  </nav>
{% endif %}

Comments

duntuk’s picture

doesn't work on drupal 7. only title is printed

looks something like this

array » Obama wins election

plus, 'phptemplate' should be replaced with 'MYTHEME' -- 'MYTHEME' should be the name of your theme folder...

(not everyone is going to know this offhand )

hence it would be helpful to most for drupal 5 & 6 versions if it looked like this:

<?php
function MYTHEME_breadcrumb($breadcrumb){
     if (!empty($breadcrumb)) {
        $breadcrumb[] = drupal_get_title();
        return '<div class="breadcrumb">'. implode(' » ', $breadcrumb) .'</div>';
    }
}
?>
stefok’s picture

replace in page.tpl.php this

    <?php if ($breadcrumb): ?>
      <div id="breadcrumb"><?php print $breadcrumb; ?></div>
    <?php endif; ?>

with this ..

<?php if ($breadcrumb): ?>
      <div id="breadcrumb">
	  <?php 
	  $temp = "</a> &raquo; <a href=\"\">" . $title . "</a></div>"; 
	  $breadcrumb = str_replace("</a></div>", $temp, $breadcrumb); 
	  print($breadcrumb);  
	  ?>
	  </div>
    <?php endif; ?>
AlexanderPop’s picture

I use
return '<div class="breadcrumb">'. implode(' &#187; ', $breadcrumb) .'</div>';
instead
return '<div class="breadcrumb">'. implode(' » ', $breadcrumb) .'</div>';
to show separator correctly

Tschet’s picture

I needed my breadcrumbs to display as an inline list. This allows for the list, and CSS gives me the inline display.

function MYTHEME_breadcrumb($breadcrumb){
     if (!empty($breadcrumb)) {
        $breadcrumb[] = drupal_get_title();
        return '<div class="breadcrumb"><ul><li>'. implode('</li><li>', $breadcrumb) .'</li></ul></div>';
    }
}
BenWrighton’s picture

When using ZEN go to: appearance > [your theme] > settings and under the title ‘Breadcrumb settings’. you can turn this on with a checkbox.

If you don't want to use ZEN it still might be worth having a look at how they did it.

francescogiannico’s picture

Hi everyone, I'm not a php expert I'm only trying to insert a breadcrumb like HOME>SECTION1>PAGE on my "views pages" but I don't know what to do...

Actually the breadcrumb appears correctly on the other pages but not on "view pages", on view pages appears only "SECTION1" and not HOME>SECTION1>PAGE

Please help me
Thaks
Francky

Rohit_Rajput’s picture

How to make breadcrumb like this.

Baseurl/page/drupal

Home> page > drupal

My breadcrumb create like this.

Home > drupal

Please give me answer. I'm w8ing....................

patelsachin444’s picture

Add this code in theme_name.theme file

/**
 * Implements hook_preprocess_breadcrumb().
 */
 function theme_name_preprocess_breadcrumb(&$variables){
  if(($node = \Drupal::routeMatch()->getParameter('node')) && $variables['breadcrumb']){
    $variables['breadcrumb'][] = array(
     'text' => $node->getTitle()
     
   );
  }
}

And then create another file in your theme's template folder named as "breadcrumb.html.twig" and put below code in this file :


{% if breadcrumb %}
  <nav class="breadcrumb" role="navigation" aria-labelledby="system-breadcrumb">
    <h2 id="system-breadcrumb" class="visually-hidden">{{ 'Breadcrumb'|t }}</h2>
    <ul>
    {% for item in breadcrumb %}
      <li>
        {% if item.url %}
          <a href="{{ item.url }}">{{ item.text }}</a>
        {% else %}
          {{ item.text }}
        {% endif %}
      </li> >
    {% endfor %}
    </ul>
  </nav>
{% endif %}

Thats it. Now flush the cache and you will get breadcrumb with current page title like Home>Current Page Title.

You can change the separator by replacing ">" with the desired one.

P.S. For Drupal 8

jasom’s picture

Here is my 5 lines

<?php if (!drupal_is_front_page()): ?>
<div class="breadcrumb">
<?php print strip_tags($breadcrumb, '<a><h2>') . ' » ' . $title;?>
</div>
<?php endif; ?>
batigol’s picture

Thanks, v helpful.

vishnu9609’s picture

Thanks Working Fine...

randomyao22’s picture

We can use hook_menu_breadcrumb_alter(&$active_trail, $item) to add new link in the end. According to this https://api.drupal.org/api/drupal/modules%21system%21system.api.php/func...

function hook_menu_breadcrumb_alter(&$active_trail, $item) {
  // Always display a link to the current page by duplicating the last link in
  // the active trail. This means that menu_get_active_breadcrumb() will remove
  // the last link (for the current page), but since it is added once more here,
  // it will appear.
  if (!drupal_is_front_page()) {
    $end = end($active_trail);
    if ($item ['href'] == $end ['href']) {
      $active_trail [] = $end;
    }
  }
}
patelsachin444’s picture

Add this code in theme_name.theme file

/**
 * Implements hook_preprocess_breadcrumb().
 */
 function theme_name_preprocess_breadcrumb(&$variables){
  if(($node = \Drupal::routeMatch()->getParameter('node')) && $variables['breadcrumb']){
    $variables['breadcrumb'][] = array(
     'text' => $node->getTitle()
     
   );
  }
}

And then create another file in your theme's template folder named as "breadcrumb.html.twig" and put below code in this file :


{% if breadcrumb %}
  <nav class="breadcrumb" role="navigation" aria-labelledby="system-breadcrumb">
    <h2 id="system-breadcrumb" class="visually-hidden">{{ 'Breadcrumb'|t }}</h2>
    <ul>
    {% for item in breadcrumb %}
      <li>
        {% if item.url %}
          <a href="{{ item.url }}">{{ item.text }}</a>
        {% else %}
          {{ item.text }}
        {% endif %}
      </li> /
    {% endfor %}
    </ul>
  </nav>
{% endif %}

Thats it. Now flush the cache and you will get breadcrumb with current page title like Home/Current Page Title.

You can change the separator by replacing "/" with the desired one.

ckrina’s picture

@patelsachin444 thank you, it works perfect. But take into account that it's a solution that only works for nodes. The documentation example works also for other kind of pages, like views generated pages.

patelsachin444’s picture

@ckrina,
I didn't notice that. Guess this is what happens when you don't test your code thoroughly :)

ThirstySix’s picture

umeshpatil’s picture

To achieve this, use below code in your custom module or create a new custom module.
I assume you already have understanding on how to create a custom module for Drupal 8/9.
Create your services file mymodule.services.yml and add below code,

      mymodule.breadcrumb_nodes:
        class: Drupal\mymodule\Breadcrumb\MyModuleBreadcrumbBuilder
        tags:
          - { name: breadcrumb_builder, priority: 10001 }

You could set key as above like breadcrumb_nodes or breadcrumb or breadcrumb_terms etc as per your needs.
Then create breadcrumb builder file under mymodule/src/Breadcrumb/ directory named as MyModuleBreadcrumbBuilder.php and add below code. In applies() method you could set your logic so that your custom builder only gets called upon satisfying your condition. Where as build() method is where you will be changing your breadcrumb.

    <?php
    
    namespace Drupal\mymodule\Breadcrumb;
    
    use Drupal;
    use Drupal\Core\Breadcrumb\Breadcrumb;
    use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
    use Drupal\Core\Link;
    use Drupal\Core\Routing\RouteMatchInterface;
    
    class MyModuleBreadcrumbBuilder implements BreadcrumbBuilderInterface {
    
      /**
       * @inheritdoc
       *  
       */
      public function applies(RouteMatchInterface $route_match) {
        // This breadcrumb will apply for all nodes.
        $parameters = $route_match->getParameters()->all();
    
        //Checking if node then only calling our builder otherwise loading default loader
        if (isset($parameters['node'])) {
         return TRUE;
        }
    
        return FALSE;
      }
    
      /**
       * @inheritdoc
       * Add your logic in below method
       */
      public function build(RouteMatchInterface $route_match) {
    
        $parameters = $route_match->getParameters()->all();
    
        $node = $parameters['node'];
    
        //Getting latest node revision
        $vid = \Drupal::entityTypeManager()->getStorage('node')->getLatestRevisionId($node->id());
        $node_new = \Drupal::entityTypeManager()->getStorage('node')->loadRevision($vid);
        $node_array = $node_new->toArray();
    
        //Creating new Breadcrumb
        $breadcrumb = new \Drupal\Core\Breadcrumb\Breadcrumb();
    
        $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
    
        $breadcrumb->addLink(Link::createFromRoute($node_array["title"][0]["value"], 'entity.node.canonical', ['node' => $node->id()]));
    
        //Adding cache control,otherwise all breadcrumb will be the same for all pages.
        //By setting a "cache context" to the "url", each requested URL gets it's
        //own cache. This way a single breadcrumb isn't cached for all pages on the
        //site.
        $breadcrumb->addCacheContexts(["url"]);
        $breadcrumb->addCacheTags(["node:{$node->id()}"]);
    
        return $breadcrumb;
      }
    }

Hope this helps.
Thanks!!

wdev’s picture

/**
 * Implements hook_preprocess_breadcrumb().
 */
function THEME_preprocess_breadcrumb(&$variables){
  //for view pages 
  $route = \Drupal::routeMatch()->getRouteObject();
  $request = \Drupal::request();
  if ($route) {
      $view_id = $route->getDefault('view_id');
      //if (!empty($view_id) && $view_id =='VIEW_ID') {
      if (!empty($view_id)) {
          $page_title = \Drupal::service('title_resolver')->getTitle($request, $route);
          $variables['breadcrumb'][] = array(
              'text' => $page_title
          );
      }
  }

  if(($node = \Drupal::routeMatch()->getParameter('node')) && $variables['breadcrumb']){
    // Adding the a divider of between home an the title of the page.
    $variables['breadcrumb'][] = array(
        'text' => '>'
    );
    // Adding the title of the page in the breadcrumb
    $variables['breadcrumb'][] = array(
        'text' => $node->getTitle(),
        'url' => $node->URL()
    );

  }
}
davedg629’s picture

For the Drupal 8 solution, I was having problems with Drupal caching and Varnish cache (not sure which is the culprit). Basically the node title was getting cached and displaying the wrong title on subsequent page loads. I had to add the cache context to the $variables array to fix the issue.

See this thread: https://drupal.stackexchange.com/questions/202159/problem-with-hook-prep...