Thursday, March 28, 2024

The Responsive Breadcrumb Trail and Sitemap

The Responsive Breadcrumb Trail and Sitemap

In the Building Responsive Web Page Headers article we learned how to construct our page header so that its optimized for both desktop and mobile devices. The same technique can be applied to the breadcrumb trail so that it switches from a horizontal layout to a vertical one depending on the viewport width. As a bonus, with a couple of additional tweaks, our breadcrumbs can double as a sitemap in the mobile view, giving the user more flexibility in choosing their next page navigation. This is all done using CSS!

The HTML Markup

Before I get into the code, I’d like to give credit where credit is due. My demo is largely based on the work of fellow Ontario resident Arley McBlain who himself credits user experience design expert Karl Stahl with the UI and Nicole Sullivan for her “media object” CSS pattern. All I did was make a few small modifications to the CSS to make my header play nicely with the breadcrumbs.

Since you’re reading this article, I can only assume that you already know what breadcrumbs (or breadcrumb trails) are, so I won’t get into that here. In case you’re fuzzy on them, here‘s a good primer. What I would like to do is talk a bit about the difference between the header navigation links and those of the breadcrumb trail. There may be considerable overlap between the two, but the header contains a static set of links to all of the major site pages whereas the breadcrumb trail contains only those that lead to the current page from the main one. Typically, they would start at the Home page and work their way down the section/page hierarchy.

For instance, here we have the links for an investment firm, arranged within an ordered list:

<!-- Header DIV would be here -->

<div id="section-title" class="section-title">Mutual Funds</div>

<ol id="sitemap" class="breadcrumb nav">
  <li><a href="#?1">Home</a></li>
  <li><a href="#?2">About</a></li>
  <li class="active"><a href="#?3">Investments</a>

    <!-- breadcrumb trail -->
    <ol>
      <li class="active"><a href="#?4">Stocks</a>
        <ol>
          <li><a href="#?5">Performance</a></li>
          <!-- no link on current page -->
          <li class="current">Expert Analysis</li>
          <li><a href="#?6">History</a></li>
        </ol>
      </li><!-- .active -->
     
      <li><a href="#?7">Mutual Funds</a>
        <ol>
          <li><a href="#?8">Performance</a></li>
          <li><a href="#?9">Fund Comparison</a></li>
          <li><a href="#?10">History</a></li>
        </ol>
      </li>
     
      <li><a href="#?11">ETFs</a>
        <ol>
          <li><a href="#?12">Performance</a></li>
          <li><a href="#?13">Fund Comparison</a></li>
          <li><a href="#?14">History</a></li>
        </ol>
      </li>
    </ol>

  </li>
  <li><a href="#?15">Loans</a></li>
  <li><a href="#?16">Contact</a></li>   
 
</ol><!-- .breadcrumb -->

While the highest level list items match the main navigation links in the header, this list also includes subpages for each investment type in the form of nested lists. The breadcrumb trail consists of:

  1. The Home page
  2. list items that have the “active” class
  3. the “current” item, i.e. the page that is presently displayed in the browser

Here is the page in desktop resolution:

header_and_breadcrumbs_in_desktop.jpg

Sass-y CSS

Sullivan’s media object is an abstraction whereby a pattern is removed from a specific idea and made into a more generic one. Doing so allows for the creation of a single more generic representation of a pattern and reuse it rather than write the same similar patterns over and over. You can see a definition of an abstraction in the .nav rule below. It contains the repeated selectors and makes them into a more granular construct. Both list items and links are assigned the display value of “inline-block”, and the IE7 hack is included to force elements to act like “inline-block” if they do not naturally support it. This transforms list elements into a very basic horizontal series of links which we can then extend to adopt more specific styles. You can read more on media object abstraction here.

Here is the CSS that controls the appearance of the breadcrumbs at a desktop-sized resolution:

@import "compass/css3";

ul, ol {
  padding:0;
}

.nav{
    list-style:none;
    margin-left:0;
}
    .nav &gt; li,
        .nav &gt; li &gt; a{
            display:inline-block;
           *display:inline;
            zoom:1;
    }


.breadcrumb {
 
  ol, li, a {
    display:block;
    float:left;
  }
 
  &:after {
    content:"";
    display:block;
    clear:both;
  }
 
  li {
    display:inline-block;
  }
 
  a,
  .current {
    padding:.5em;
  }
  a {
    text-decoration:none;
  }
 
}

// Desktop first!
.section-title {
  display:none;
}
.breadcrumb a:after {
  content: " >";
}

// Don't show the whole sitemap, just the active trail
.breadcrumb &gt; li {
  display:none;

  &:first-child, // Home button exception
  &.active,
  &.current {
    display:inline-block;
  }
   
  li { // active section siblings
      display:none;
     
      &.active,
      &.current {
        display:block;
        //padding: .5em;
      }
    } // li
} // sitemap &gt; li
@media (min-width:48em) { // 768px
  .breadcrumb {
    display:block !important;
  }
}

Notice the import statement at the top? That imports Sass 3. It’s a popular CSS preprocessor that extends CSS by allowing developers to write specialized code that is then compiled into CSS. Precompilers like Sass let you nest your CSS selectors in such a was as to mimic your HTML hierarchy as well as include special characters like ampersands (&). The latter comes in handy when you’re nesting and you want to create a more specific selector. Utilized within a nested selector, the ‘&’ character always refers to the parent selector.

These days devices are reporting device pixel widths that are no longer accurate. Pixels don’t mean pixels anymore; the iPad mini for example is 40% smaller than an actual iPad but it reports the same width as the regular size one. Moreover, retina devices are 2 mega pixels. Using px-based media queries will result in very, very small designs on these devices. To avoid this, use em-based media queries. Then only use percentages (or ems) on containers.

The following table shows devices and their respective viewport sizes in both ems and pixels:

Small Phone Phone Tablet Laptop Desktop
Estimated
Devices
Small Phones Phones to
Tablet size
Small Tablets
Large Tablets
Netbooks
Laptops
small Desktops
Average to
Large Desktops
Width 30em (480px)& lower Below
48em (768px)
48 em (768px) & above 62 em (992px) & above 75em (1200px) & above

The media query below sets the max-width to 47.938em so that there is no overlap between phone-sized devices and tablets.

// Mobile
@media (max-width:47.938em) { // 767px
  .section-title {
    display:block;
    padding:1em;
    background:#666;
    color:white;
    cursor:pointer;
    margin-top:0;
   
    &:hover {
      background:lightgray;
      color: black;
    }
   
    &:before {
      content:"? ";
    }
    &.open:before {
      content: "? ";
    }
  } // .section-title

  .breadcrumb {
    padding:1em;
    margin:0;
    background: #e8e8e8;
    border:1px solid #eee;
    border-top:0;
    // Uncomment this to make the dropdown go on top of the content.
    //position:absolute;
   
    display:none;
   
    ol, li, a {
      float:none;
    }
    .current:before {
        content:"? ";       
    }
   
    li {
      display:block;
      float:none;
    }
    a:after {
      content: "";
    } // a

 
     > li { 
      &:first-child,
      &.active,
      &.current {
        display:block;
      }
   
      li {
        padding-left:1em;
        display: block;
      }
    } // > li
  }// .breadcrumb
}

Here is the breadcrumb presented as a sitemap in mobile devices:

header_and_breadcrumbs_in_mobile.jpg

The JavaScript Code

In mobile mode, clicking the section title displays the site hierarchy. Unlike the header menu, whose animation is controlled using CSS, the breadcrumbs’ animation is handled by jQuery via the call to slideToggle(). It goes to show that there is more than one way to accomplish the same task in modern browsers.

$('#section-title').click(function() {
  $('#sitemap').slideToggle();
  $(this).toggleClass('open');
});

Conclusion

I’ve posted a working demo on Codepen.io for you to play with. For the purposes of the demo, the links don’t actually point anywhere, but feel free to click them!

Rob Gravelle
Rob Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured