<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"
}
// 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);
}
}
});
// 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;
}
}
}
}
}
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.
Animation is applied by adding the make-inview
class to the individual breadcrumb items. Animation will trigger when the breadcrumb moves into the viewport.
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.