I am hoping to accomplish some shrinking breadcrumb stuff (hopefully without js... but i can settle for vanilla js)

I have an unknown number of items that need to go in a breadcrumb like thing (not navigatable)

What I want is enter image description here

where the active item is always readable, and if there are few enough items they are all readable (ie the inactive tabs scale their width to fit the available width, left after ensuring the active item is entirely visible) Ive followed a tutorial and gotten it pretty close (but i cant figure out how to scale it)

what i get is enter image description here

/* BREADCRUMBS.CSS */
ul.breadcrumb {
  list-style: none;
  width: 460px;
  height: 40px;
  border-radius: 2px;
  border: solid 1px #d2d2d2;
}

ul.breadcrumb li {
  float: left;
  border-top: 1px solid #d2d2d2;
  border-bottom: 1px solid #d2d2d2;
  font: 14px Roboto, "Helvetica Neue", sans-serif;
}
ul.breadcrumb li:first-of-type {
  border-left: 1px solid #d2d2d2;
}

ul.breadcrumb li span.inner {
  overflow: hidden;
  direction: rtl;
  white-space: nowrap;
  /* keeps everything on one line */
  width: 100%;
}

ul.breadcrumb li {
  color: #4a4a4a;
  font-weight: bold;
  text-decoration: none;
  padding: 10px 0 10px 40px;
  background: #F5F5F5;
  position: relative;
  display: block;
  min-width: 10px;
  float: left;
  padding-right: 1em;
}

ul.breadcrumb li.active {
  color: #396d9a;
  background: white;
  min-width: 150px;
}

ul.breadcrumb li::before {
  content: " ";
  display: block;
  width: 0;
  height: 0;
  border-top: 22px solid transparent;
  border-bottom: 21px solid transparent;
  border-left: 12px solid #d2d2d2;
  position: absolute;
  top: 50%;
  margin-top: -22px;
  margin-left: 1px;
  left: 100%;
  z-index: 1;
}

ul.breadcrumb li::after {
  content: " ";
  display: block;
  width: 0;
  height: 0;
  border-top: 22px solid transparent;
  /* Go big on the size, and let overflow hide */
  border-bottom: 21px solid transparent;
  border-left: 12px solid #F5F5F5;
  position: absolute;
  top: 50%;
  margin-top: -22px;
  left: 100%;
  z-index: 2;
}

ul.breadcrumb li.active::after {
  border-left: 12px solid white;
}

ul.breadcrumb li:last-child {
  border-right: 1px solid #d2d2d2;
  padding-right: 1em;
}
ul.breadcrumb li:last-child::before {
  display: none;
  border: none;
}
ul.breadcrumb li:last-child::after {
  display: none;
  border: none;
}
<!-- breadcrumbs.html  !-->
Example 1. Works fine with a couple of items
<ul class="breadcrumb ng-star-inserted">
  <li class="active ng-star-inserted"><span class="inner">CLEAN DEVICE</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
</ul>

<hr/>

How Do i make inactive items shrink (and hide text as needed) so they all fit on the same row? while keeping the active tabs text visible
<ul class="breadcrumb ng-star-inserted">
  <li class="active ng-star-inserted"><span class="inner">CLEAN DEVICE</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
    <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
</ul>

(as an aside, im not married to any of the concepts in here (ie if this is easier with elements other than ul)) ... basically im just terrible at css :(

2 Answers

2
kukkuz On Best Solutions

You can try flexbox for this:

  • add display: flex to the ul (optionally override its default padding),

  • add flex: 0 0 auto to the first and last li (this is a shorthand that says that a flex item should not grow or shrink but take only its auto width),

  • and optionally remove the min-width of the first li too.

See demo below:

/* BREADCRUMBS.CSS */
ul.breadcrumb {
  list-style: none;
  width: 460px;
  height: 40px;
  border-radius: 2px;
  border: solid 1px #d2d2d2;
  display: flex; /* added */
  padding: 0; /* added */
}

ul.breadcrumb li {
  float: left;
  border-top: 1px solid #d2d2d2;
  border-bottom: 1px solid #d2d2d2;
  font: 14px Roboto, "Helvetica Neue", sans-serif;
}
ul.breadcrumb li:first-of-type {
  border-left: 1px solid #d2d2d2;
}

ul.breadcrumb li span.inner {
  overflow: hidden;
  direction: rtl;
  white-space: nowrap;
  /* keeps everything on one line */
  width: 100%;
}

ul.breadcrumb li {
  color: #4a4a4a;
  font-weight: bold;
  text-decoration: none;
  padding: 10px 0 10px 40px;
  background: #F5F5F5;
  position: relative;
  display: block;
  min-width: 10px;
  float: left;
  padding-right: 1em;
}

ul.breadcrumb li.active {
  color: #396d9a;
  background: white;
  /*min-width: 150px;*/
  flex: 0 0 auto; /* added */
}

ul.breadcrumb li::before {
  content: " ";
  display: block;
  width: 0;
  height: 0;
  border-top: 22px solid transparent;
  border-bottom: 21px solid transparent;
  border-left: 12px solid #d2d2d2;
  position: absolute;
  top: 50%;
  margin-top: -22px;
  margin-left: 1px;
  left: 100%;
  z-index: 1;
}

ul.breadcrumb li::after {
  content: " ";
  display: block;
  width: 0;
  height: 0;
  border-top: 22px solid transparent;
  /* Go big on the size, and let overflow hide */
  border-bottom: 21px solid transparent;
  border-left: 12px solid #F5F5F5;
  position: absolute;
  top: 50%;
  margin-top: -22px;
  left: 100%;
  z-index: 2;
}

ul.breadcrumb li.active::after {
  border-left: 12px solid white;
}

ul.breadcrumb li:last-child {
  border-right: 1px solid #d2d2d2;
  padding-right: 1em;
  flex: 0 0 auto; /* added */
}
ul.breadcrumb li:last-child::before {
  display: none;
  border: none;
}
ul.breadcrumb li:last-child::after {
  display: none;
  border: none;
}
<!-- breadcrumbs.html  !-->
Example 1. Works fine with a couple of items
<ul class="breadcrumb ng-star-inserted">
  <li class="active ng-star-inserted"><span class="inner">CLEAN DEVICE</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
</ul>

<hr/>

How Do i make inactive items shrink (and hide text as needed) so they all fit on the same row? while keeping the active tabs text visible
<ul class="breadcrumb ng-star-inserted">
  <li class="active ng-star-inserted"><span class="inner">CLEAN DEVICE</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
    <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
</ul>

1
Dacre Denny On

One approach would be to use flex-box to achieve adaptive sizing of breadcrumb elements as required.

Also, to achieve the fade out effect, you could introduce a pseudo element that has a linear-gradient fading from transparent to the background grey color, on the inner span for pending list items.

The CSS adjustments below should achieve what you require:

/* Use flex box to auto size width of breadcrumb elements */
ul.breadcrumb {
  display:flex;
  flex-direction:row;
}

/* Update styling of inner span to position with absolute so
that left and right extents can be set */
ul.breadcrumb li.pending span.inner {
  position:absolute;
  width:unset;
  left:1.5rem;
  right:0;
  direction:ltr;
}

/* Create pseudo element on inner span which overlays graidient
to achieve fade-out effect */
ul.breadcrumb li.pending span::after {
  content: '';
    display: block;
    position: absolute;
    right: 0;
    top: 0;
    height: 100%;
    width: 100%;
    background: linear-gradient(90deg, transparent,#F5F5F5);
}

/* BREADCRUMBS.CSS */
ul.breadcrumb {
  list-style: none;
  width: 460px;
  height: 40px;
  border-radius: 2px;
  border: solid 1px #d2d2d2;
}

ul.breadcrumb li {
  float: left;
  border-top: 1px solid #d2d2d2;
  border-bottom: 1px solid #d2d2d2;
  font: 14px Roboto, "Helvetica Neue", sans-serif;
}
ul.breadcrumb li:first-of-type {
  border-left: 1px solid #d2d2d2;
}

ul.breadcrumb li span.inner {
  overflow: hidden;
  direction: rtl;
  white-space: nowrap;
  /* keeps everything on one line */
  width: 100%;
}

ul.breadcrumb li {
  color: #4a4a4a;
  font-weight: bold;
  text-decoration: none;
  padding: 10px 0 10px 40px;
  background: #F5F5F5;
  position: relative;
  display: block;
  min-width: 10px;
  float: left;
  padding-right: 1em;
}

ul.breadcrumb li.active {
  color: #396d9a;
  background: white;
  min-width: 150px;
}

ul.breadcrumb li::before {
  content: " ";
  display: block;
  width: 0;
  height: 0;
  border-top: 22px solid transparent;
  border-bottom: 21px solid transparent;
  border-left: 12px solid #d2d2d2;
  position: absolute;
  top: 50%;
  margin-top: -22px;
  margin-left: 1px;
  left: 100%;
  z-index: 1;
}

ul.breadcrumb li::after {
  content: " ";
  display: block;
  width: 0;
  height: 0;
  border-top: 22px solid transparent;
  /* Go big on the size, and let overflow hide */
  border-bottom: 21px solid transparent;
  border-left: 12px solid #F5F5F5;
  position: absolute;
  top: 50%;
  margin-top: -22px;
  left: 100%;
  z-index: 2;
}


ul.breadcrumb li.active::after {
  border-left: 12px solid white;
}

ul.breadcrumb li:last-child {
  border-right: 1px solid #d2d2d2;
  padding-right: 1em;
}
ul.breadcrumb li:last-child::before {
  display: none;
  border: none;
}
ul.breadcrumb li:last-child::after {
  display: none;
  border: none;
}
<!-- breadcrumbs.html  !-->
Example 1. Works fine with a couple of items
<ul class="breadcrumb ng-star-inserted">
  <li class="active ng-star-inserted"><span class="inner">CLEAN DEVICE</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
</ul>

<hr/>

How Do i make inactive items shrink (and hide text as needed) so they all fit on the same row? while keeping the active tabs text visible
<ul class="breadcrumb ng-star-inserted">
  <li class="active ng-star-inserted"><span class="inner">CLEAN DEVICE</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
    <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
  <li class="pending ng-star-inserted"><span class="inner">Reading</span></li>
</ul>