SharePoint 2013 and the Disappearing Breadcrumb

Several changes were introduced in the SharePoint 2013 UI, one of which that caught the attention of a lot of folks was the removal of the breadcrumb. Through the years the SharePoint breadcrumb had met some interesting treatments, but in 2013 it had simply just disappeared.

Truth be told, the breadcrumb is still there, just hidden away in the master page. With a quick master page edit you can get breadcrumb back into SharePoint – but that is when the real fun begins as the SharePoint breadcrumb comes in many flavors.

Adding back the pop-out breadcrumb

Before we dive into the finer intricacies of the breadcrumb including data source and display, let’s get the dang thing back into SharePoint. You will need master page access and editing rights for this exercise.

  1. Open up your master page (.master) in SharePoint Designer or open your HTML master page file (.html) in an editor of your choice if you use Design Manager.
  2. Search for “PopoutMenu“. More than likely you should come up with two results, the opening and closing tags of a control. If you are using Design Manager then there is a good chance you won’t find the code block (and that is OK I have a copy for you below).
  3. You should be looking at the following code block. If you didn’t find it and need a copy for your master page/HTML file, here you go:
    <SharePoint:PopoutMenu Visible="false" runat="server" ID="GlobalBreadCrumbNavPopout" IconUrl="/_layouts/15/images/spcommon.png?rev=23" IconAlt="<%$Resources:wss,master_breadcrumbIconAlt%>" ThemeKey="v15breadcrumb" IconOffsetX="215" IconOffsetY="120" IconWidth="16" IconHeight="16" AnchorCss="ms-breadcrumb-anchor" AnchorOpenCss="ms-breadcrumb-anchor-open" MenuCss="ms-breadcrumb-menu ms-noList">
    <div class="ms-breadcrumb-top">
    	<asp:Label runat="server" CssClass="ms-breadcrumb-header" Text="<%$Resources:wss,master_breadcrumbHeader%>" />
    </div>
    
    <asp:ContentPlaceHolder id="PlaceHolderTitleBreadcrumb" runat="server">
    	<SharePoint:ListSiteMapPath runat="server" SiteMapProviders="SPSiteMapProvider,SPContentMapProvider" RenderCurrentNodeAsLink="false" PathSeparator="" CssClass="ms-breadcrumb" NodeStyle-CssClass="ms-breadcrumbNode" CurrentNodeStyle-CssClass="ms-breadcrumbCurrentNode" RootNodeStyle-CssClass="ms-breadcrumbRootNode" NodeImageOffsetX="217" NodeImageOffsetY="210" NodeImageWidth="16" NodeImageHeight="16" NodeImageUrl="/_layouts/15/images/spcommon.png?rev=23" RTLNodeImageOffsetX="199" RTLNodeImageOffsetY="210" RTLNodeImageWidth="16" RTLNodeImageHeight="16" RTLNodeImageUrl="/_layouts/15/images/spcommon.png?rev=23" HideInteriorRootNodes="true" SkipLinkText="" />
    </asp:ContentPlaceHolder>
    </SharePoint:PopoutMenu>
  4. Right from the get-go the culprit is discovered. The breadcrumb control is still there, just set to not show through the Visible=”false” property/value pair. If you change false to true or just remove the property altogether, the pop-out breadcrumb will appear. Here is a visual reminder for which breadcrumb system this is (it’s a throwback to SharePoint 2010).
    Pop-out breadcrumb added back to SharePoint
  5. If the pop-out breadcrumb did not appear after modifying the control, look above the control in the code and see if the control is being wrapped by this DIV, which has an inline style with the display set to none:
    <div class="ms-breadcrumb-dropdownBox" style="display:none;">

    Remove the inline style and you should be good to go.

  6. If you navigate deeper into your site the breadcrumb will kick in and provide a way to access parent elements when you click on the folder icon.

If this is what you wanted to add back in SharePoint, then you are good to go and can stop here.  If you want to add a more traditional breadcrumb…. then continue forth.  🙂

Adding back the traditional breadcrumb

When I say traditional breadcrumb, I am referring to what you see on most web sites, a trail of where you have been separated by some special character.  For example:

Home > About Us > Why We Are Awesome

This breadcrumb style was available in SharePoint 2010 (it was parading as a fancy jumbocrumb title), but disappeared in 2013. Unfortunately it is not just lurking in the master page code waiting to be set to show again.  To add this breadcrumb you need to go back to SharePoint 2010 and copy the code from there.

  1. Open up your master page (.master) in SharePoint Designer or open your HTML master page file (.html) in an editor of your choice if you use Design Manager.
  2. Locate where you want to add the breadcrumb in your code. Paste in the following control:
    <asp:SiteMapPath runat="server" SiteMapProviders="SPSiteMapProvider,SPXmlContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/>

    If you are using a HTML master page file (Design Manager) you will need to dress up the code just a bit:

    <!--MS:<asp:SiteMapPath runat="server" SiteMapProviders="SPSiteMapProvider,SPXmlContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/>-->

On a side note, the real meat to breadcrumb controls is the SiteMapProviders property/value pair. In other articles on the web you will see this same control but with a SiteMapProvider value of CurrentNavSiteMapProviderNoEncode.  I have found what is used above (SPSiteMapProvider,SPXmlContentMapProvider) and CurrentNavSiteMapProviderNoEncode to be interchangeable with no resulting difference on the page.  If you experience something else, please let me know in the comments.

Here is the result:
Using a SharePoint 2010 control to add traditional breadcrumb to 2013

Fast, clean and easy, this is a great way to add traditional breadcrumb to your publishing sites for use on publishing pages only. If this fits the bill for your needs, you can go grab that latte now.  If not, carry on.   🙂

Wait, you said publishing pages only?

If you poke around your site a bit more with the traditional breadcrumb in place, you will see that it becomes useless on lists and libraries and non-publishing sites other than link you to the parent site (and sometimes that doesn’t even work).  Here are a couple of example screenshots from various non-publishing areas in the site:

Documents list in a publishing site
Document library in the publishing site. Note the breadcrumb is empty aside from the parent site name (which is not a link because the RenderCurrentNodeAsLink property was not added with a value of True).
Document library screen in a Team Site
Document library in a child team site. Note the breadcrumb only lists the parent site and not the library name.
List item in an announcements list in the team site
Open list item in an announcements list in a child team site. Note the breadcrumb only lists the parent site and not the list name or list item title.

Tweak the SiteMapProvider for a different outcome

If you make a slight change to the SiteMapProvider property in the control you will get a different outcome in the various scenarios. Remember that SiteMapProvider is where the party is at as it is pulling in the content that will be displayed.

Return to your file and the asp:SiteMapPath control. Replace this:

SiteMapProviders="SPSiteMapProvider,SPXmlContentMapProvider"

With this:

SiteMapProvider="SPContentMapProvider"

Altering the value isn’t the only change going on here. Note that in the original code snippet it was SiteMapProviders (with an S) and in the revised code snippet it is now SiteMapProvider (no S).

Here are the results on the same three pages demonstrated before:

Document library in the publishing site.
Document library in the publishing site. Note the breadcrumb includes the library name now and the parent item is a link (since there is a child element the parent will be linked).
Document library screen in a Team Site
Document library in a child team site. Note the breadcrumb now lists the library name.
List item in an announcements list in the team site
Open list item in an announcements list in a child team site. Note the breadcrumb now includes the list name and list item title.

Yay! Right?   Wrong.  Check out publishing pages now:

Top level site collection home page
Home page now includes the “Pages” library in the breadcrumb path.
Sub page under top level site collection.
Sub page in the top level site collection now includes a second level where none should be.
Sub page in a sub site
Sub page in a sub site under the top level site collection. Third level isn’t necessary.

There isn’t a best of both worlds solution with the SiteMapPath control.

Traditional breadcrumb – control option #2

SharePoint is ripe with many ways to do one thing and breadcrumb is no exception. The following control will also generate a traditional breadcrumb, and you can even put this in your code alongside the asp:SiteMapPath control so you can do some side by side comparisons:

<SharePoint:ListSiteMapPath runat="server" SiteMapProviders="SPContentMapProvider" RenderCurrentNodeAsLink="false" PathSeparator="" CssClass="ms-breadcrumb" NodeStyle-CssClass="ms-breadcrumbNode" CurrentNodeStyle-CssClass="ms-breadcrumbCurrentNode" RootNodeStyle-CssClass="ms-breadcrumbRootNode" NodeImageOffsetX="217" NodeImageOffsetY="210" NodeImageWidth="16" NodeImageHeight="16" NodeImageUrl="/_layouts/15/images/spcommon.png?rev=23" RTLNodeImageOffsetX="199" RTLNodeImageOffsetY="210" RTLNodeImageWidth="16" RTLNodeImageHeight="16" RTLNodeImageUrl="/_layouts/15/images/spcommon.png?rev=23" HideInteriorRootNodes="true" SkipLinkText="" />

You will need this for a HTML master page file (Design Manager):

<!--MS:<SharePoint:ListSiteMapPath runat="server" SiteMapProviders="SPContentMapProvider" RenderCurrentNodeAsLink="false" PathSeparator="" CssClass="ms-breadcrumb" NodeStyle-CssClass="ms-breadcrumbNode" CurrentNodeStyle-CssClass="ms-breadcrumbCurrentNode" RootNodeStyle-CssClass="ms-breadcrumbRootNode" NodeImageOffsetX="217" NodeImageOffsetY="210" NodeImageWidth="16" NodeImageHeight="16" NodeImageUrl="/_layouts/15/images/spcommon.png?rev=23" RTLNodeImageOffsetX="199" RTLNodeImageOffsetY="210" RTLNodeImageWidth="16" RTLNodeImageHeight="16" RTLNodeImageUrl="/_layouts/15/images/spcommon.png?rev=23" HideInteriorRootNodes="true" SkipLinkText="" />-->

And this is the result (trimming the fat from the images from here on out):

List item in an announcements list in the team site
List item in an announcements list in the team site.
Sub page in a sub site
Sub page in a sub site.

The odd design aside, we are getting the same results as the singular SPContentMapProvider value as the previous SiteMapPath control. This makes sense as the provider data is the same, the only thing that is different is how it is being churned out for display.

You can mess around with the SiteMapProvider(s) just like before but you will only end up with ‘great for publishing’ or ‘great for lists/non-publishing sites’ but not ‘great for both’ results. Using this control will also require style editing to weed out the arrows and line up the nav items instead of the default vertical cascade.

So what to do?

Publishing sites

For publishing site environments that are more brochureware sites that don’t surface non-publishing sites or lists/libraries to end users, just go with the asp:SiteMapPath control using “SPSiteMapProvider,SPXmlContentMapProvider” or “CurrentNavSiteMapProviderNoEncode” for the SiteMapProvider(s) value.  If you have lists/libraries that provide data for Data View Web Parts, Display Templates, Content Search Web Parts, etc. that is fine.  Just as long as you don’t show the end user the raw list or library view.   If you do show the raw list/library and don’t care that the breadcrumb doesn’t match well with it, then this version of the SiteMapPath control is fine to use.

<asp:SiteMapPath runat="server" SiteMapProviders="SPSiteMapProvider,SPXmlContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/>

HTML master page file (Design Manager):

<!--MS:<asp:SiteMapPath runat="server" SiteMapProviders="SPSiteMapProvider,SPXmlContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/>-->

Non-publishing sites

For non-publishing sites (team sites, blogs, project sites, etc.) you can use the asp:SiteMapPath control using “SPContentMapProvider” for the SiteMapProvider value.

<asp:SiteMapPath runat="server" SiteMapProvider="SPContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/>

Mixed publishing and non-publishing environment or publishing site that uses lists/libraries

Option 1: Utilize Page Layouts **Best choice**

Since you are already using publishing, might as well put it to work. In your master page, add the non-publishing friendly SiteMapPath control and wrap it in a custom ContentPlaceHolder. For example:

<asp:ContentPlaceHolder id="customBreadcrumb" runat="server">
    <asp:SiteMapPath runat="server" SiteMapProvider="SPContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/>
</asp:ContentPlaceHolder>

In your page layout files, which are only used on publishing pages, add a content control and override the breadcrumb:

<asp:Content ContentPlaceholderID="customBreadcrumb" runat="server">
    <asp:SiteMapPath runat="server" SiteMapProviders="SPSiteMapProvider,SPXmlContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/>
</asp:Content>

Do this for all of your page layout files.

Option 2: Multiple master pages

In the Master Page settings within Site Actions -> Site Settings, you have the ability to set a master page for publishing pages (only applies to ASPX files saved in the Pages library) and a separate master page for non-publishing pages. You could create two different master pages, using the appropriate SiteMapPath control in each. Unless you have a multitude of other reasons to have multiple master pages, I don’t suggest this approach. Breadcrumb is too small of a thing to justify multiple master pages.

Option 3: Utilize CSS

This solution isn’t potentially as rock solid as the ones listed above – it all depends on your individual site and needs.

You can actually use both versions of the SiteMapPath control in a single master page, resulting in a double breadcrumb. If you wrap each one with an HTML tag (DIV, SPAN, NAV, etc.) with a class assigned to it, you can pick and choose which breadcrumb to show based on where you are in the site. For example, this would go in the master page:

<span class="breadcrumb-nonpub"><asp:SiteMapPath runat="server" SiteMapProvider="SPContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/></span>
<span class="breadcrumb-pub"><asp:SiteMapPath runat="server" SiteMapProviders="SPSiteMapProvider,SPXmlContentMapProvider" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="breadcrumbNode" CurrentNodeStyle-CssClass="breadcrumbCurrentNode" RootNodeStyle-CssClass="breadcrumbRootNode" HideInteriorRootNodes="true" SkipLinkText=""/></span>

Here are the two CSS style statements that would be put to use:

.breadcrumb-nonpub {
  display: none;
}

.breadcrumb-pub {
  display: none;
}

Now it is just a matter of selectively applying the CSS based on publishing vs. non-publishing scenarios. First you will need to either set both to be hidden by default in your main CSS file, or pick one to hide by default in your main CSS file. Then you will need to add countering CSS to show/hide the breadcrumb as appropriate. For example:

  • If your page layouts are linking to a CSS file, or have a style block added to the HEAD of the site via the PlaceHolderAdditionalPageHead content control, by default hide the publishing breadcrumb and in the page layout CSS hide the non-publishing breadcrumb and show the publishing breadcrumb.
  • If you want documents and lists to show the non-publishing breadcrumb, you can expand the CSS selector to look for the presence of “Forms” or “Lists” in the action property of the FORM tag. Use this to create a descendent selector for your CSS:
    form[action*="Forms"] .breadcrumb-pub,
    form[action*="Lists"] .breadcrumb-pub {
      display: none;
    }
    
    form[action*="Forms"] .breadcrumb-nonpub,
    form[action*="Lists"] .breadcrumb-nonpub {
      display: inline-block;
    }
  • You can also use JavaScript to expand your BODY tag to include custom classes based on the structure of your site. Then use those classes in a descendant CSS selector to show/hide breadcrumb based on location. Check out Multiple Sites with Varying Designs in a Single CSS File for more info on how to do this.