<nav aria-label="breadcrumb">
    <ol class="breadcrumb p-0 w-100 d-flex flex-nowrap rounded-0">
        <li class="breadcrumb-item"><a href="#">Home</a></li>
        <li class="breadcrumb-item"><a href="#">Link Name</a></li>
        <li class="breadcrumb-item"><a href="#">Link Name</a></li>
        <li class="breadcrumb-item active" aria-current="page"><span class="current">Current Page Name</span></li>
    </ol>
</nav>
<nav aria-label="breadcrumb">
  <ol class="breadcrumb p-0 w-100 d-flex flex-nowrap rounded-0">
    {{> @breadcrumb-item }}{{ render '@breadcrumb-item' }}{{ render '@breadcrumb-item' }}{{ render '@breadcrumb-item--active' }}
  </ol>
</nav>
{
  "bi_classes": "",
  "bi_ariacurrent": "",
  "bi_innertag": "a",
  "bi_innertag_attr": " href=\"#\"",
  "bi_innertext": "Home"
}
  • Content:
    // javascript to switch from small to large screen configuration, using intersection observer and resize observer
    
    // start from large screen configuration, check to see if the breadcrumb is being cut off
    
    document.addEventListener("DOMContentLoaded", function() {
      if ("IntersectionObserver" in window) { // if available
        
        // identify the breadcrumb
        var b = document.querySelector(".breadcrumb");
        
        // is there a breadcrumb?
        if (b !== null && b !== undefined) {
        
          // identify the current page title
          var c = document.querySelector(".breadcrumb .current");
    
          // identify the items in the breadcrumb that are not the first or last items
          var i = Array.from(b.querySelectorAll("li"));
          i.splice(0,1);
          i.splice(-1,1);
          // console.log(i);
    
          // get the approximate width of the breadcrumb at full size as an initial value
          var w = 0;
          b.querySelectorAll("li *:first-child").forEach(item => w += item.scrollWidth);
          // console.log({w});
    
          // inner HTML code for the small screen dropdown item
          var dropdown_html = '<a href="#" role="button" id="littlecrumbs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">…</a><div class="dropdown-menu" aria-labelledby="littlecrumbs"></div>';
    
          // options for the intersection observer
          var c_observer_options = {
            root: document.querySelector('.breadcrumb li:last-child'),
            rootMargin: '0px',
            threshold: 0.95
          }
        
          // callback for the intersection observer
          var c_observer_callback = function(entries, observer) {
            entries.forEach(function(entry) {
              var is_smaller = entry.intersectionRatio <= 0.94999999;
              // console.log({is_smaller});
    
              // if the screen is too small, change to the small screen context
              // and then observe for when the breadcrumb is big enough again for the large screen context
              if (is_smaller) {
    
                // stop observing intersections
                c_observer.unobserve(c);
    
                // transition to small screen context
                b.classList.add('smallscreen');
                var items = b.querySelectorAll("li");
                if (items.length > 2) {
                  for(var x=1;x<(items.length - 1);x++) {
                    items[x].parentNode.removeChild(items[x]);
                  }
                }
                var dropdown = document.createElement("li");
                dropdown.className = "dropdown breadcrumb-item";
                dropdown.innerHTML = dropdown_html;
                c.parentNode.before(dropdown);
                for (var y=0;y < i.length;y++) {
                  var l = i[y].querySelector('a').cloneNode(true);
                  l.className = "dropdown-item";
                  b.querySelector('.dropdown .dropdown-menu').append(l);
                }
    
                // if resize observer is supported, do it
                if (ResizeObserver) {
    
                  // observer for the breadcrumb
                  const b_observer = new ResizeObserver(entries => {
                    for (let entry of entries) {
                      var size = entry.contentRect.width;
                      // console.log({size});
                      if (size > w) {
    
                        // start the intersection observer again
                        c_observer.observe(c);
    
                        // stop the resize observer
                        b_observer.unobserve(b);
    
                        // exit the small screen context
                        b.classList.remove('smallscreen');
                        var dd = b.querySelector('.dropdown');
                        dd.parentNode.removeChild(dd);
                        for (var y=0;y < i.length;y++) {
                          c.parentNode.before(i[y]);
                        }
                      }
                    }
                  });
                  b_observer.observe(b);
                }
              }
    
            });
          };
    
          // define the observer
          let c_observer = new IntersectionObserver(c_observer_callback,c_observer_options);
    
          // apply the observer to the items
          c_observer.observe(c);
        }
      }
    });
  • URL: /components/raw/breadcrumb/breadcrumb.js
  • Filesystem Path: source/patterns/organisms/breadcrumb/breadcrumb.js
  • Size: 4.1 KB
  • Content:
    // pattern styles
    $breadcrumb-item-timing:0.25s;
    .breadcrumb {
      background-color:white;
      .breadcrumb-item {
        &:first-child {
          min-width:3.125rem;
          & > a {
            clip-path:polygon(0% 0%, (calc(100% - 0.75rem)) 0%, 100% 50%, calc(100% - 0.75rem) 100%, 0% 100%, 0 50%);
            padding-left:0.75rem;
          }
        }
        &:nth-last-child(2) {
          transition:opacity ($breadcrumb-item-timing + 0.1s);
          &.inview {
            animation:breadcrumb-item-slide ($breadcrumb-item-timing + 0.1s) ease-in-out;
          }
        }
        &:nth-last-child(3) {
          transition:opacity ($breadcrumb-item-timing + 0.2s);
          &.inview {
            animation:breadcrumb-item-slide ($breadcrumb-item-timing + 0.2s) ease-in-out;
          }
        }
        &:nth-last-child(4) {
          transition:opacity ($breadcrumb-item-timing + 0.3s);
          &.inview {
            animation:breadcrumb-item-slide ($breadcrumb-item-timing + 0.3s) ease-in-out;
          }
        }
        &:nth-last-child(5) {
          transition:opacity ($breadcrumb-item-timing + 0.4s);
          &.inview {
            animation:breadcrumb-item-slide ($breadcrumb-item-timing + 0.4s) ease-in-out;
          }
        }
        &:nth-last-child(6) {
          transition:opacity ($breadcrumb-item-timing + 0.5s);
          &.inview {
            animation:breadcrumb-item-slide ($breadcrumb-item-timing + 0.5s) ease-in-out;
          }
        }
        &.dropdown {
          overflow:visible;
        }
        & + .breadcrumb-item {
          padding-left:0;
          &::before {
            display:none;
          }
        }
      }
      &.smallscreen {
        li:first-child {
          a {
            font-size:0;
            &:before {
              content: "\f015";
              display:block;
              font-family:"Font Awesome 5 Free";
              -webkit-font-smoothing: antialiased;
              font-size:1rem;
              font-style: normal;
              font-variant: normal;
              font-weight:900;
              text-rendering:auto;
            }
          }
        }
      }
    }
  • URL: /components/raw/breadcrumb/breadcrumb.scss
  • Filesystem Path: source/patterns/organisms/breadcrumb/breadcrumb.scss
  • Size: 1.9 KB

Breadcrumb

Purpose

The Breadcrumb component builds on the default provided by Bootstrap. It uses a common breadcrumb pattern style where each item in the breadcrumb is shaped as an “arrow” pointing to the currently active item.

This implementation is different from others in that it does not depend on CSS pseudo-elements to make the arrow shaped pieces. Instead, CSS clip-path is used to shape each item in the breadcrumb trail as appropriate.

Animated Variant

Animation is applied by adding the make-inview class to the individual breadcrumb items. Animation will trigger when the breadcrumb moves into the viewport.

Responsive Behavior

The Intersection Observer API and the Resize Observer API are used to trigger collapse or expansion of the breadcrumb as needed, regardless of the width of the breadcrumb. No CSS media query is needed.

When contracted, the text of first breadcrumb item becomes the “home” icon; the middle breadcrumb items collaps into a single dropdown trigger. Clicking on the dropdown trigger displays the full name of each item in the middle of the breadcrumb trail.