I stumbled upon an interesting HTML5 feature (or bug) that makes it possible to create a material design indeterminate progress bar in pure CSS. When a div uses flex display, the :before pseudo-element is painted over it, and support margins. This means that the :before pseudoelement can look as if it’s moving on top of the element, without any JavaScript or adding additional DOM elements. Here it is in action:

I’ve tested this in the current versions of Chrome, Firefox and (OSX and mobile) Safari, and it seems to work well. According to Can I Use, CSS animations work in all the major browsers now apart from Opera Mini, and Flexbox display is now generally supported, so this trick should be OK for general use as long as you don’t need support for old browsers. MS browsers might need some CSS prefixes on the classes for this to work, but IE is not on my critical path so I’ve not tested that.

How it works

Inspect the source, and you’ll find only a normal div with a single class associated with it.

<div class="progress-line"></div>

The CSS is essentially using the main div background colour for the neutral background of the progress bar, and the :before pseudoelement background colour for the active moving part. By animating the margin-left and margin-right of the :before pseudoelement, the active background races across the neutral one.

.progress-line, .progress-line:before {
  height: 3px;
  width: 100%;
  margin: 0;
}
.progress-line {
  background-color: #b3d4fc;
  display: -webkit-flex;
  display: flex;
}
.progress-line:before {
  background-color: #3f51b5;
  content: '';
  -webkit-animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@-webkit-keyframes running-progress {
  0% { margin-left: 0px; margin-right: 100%; }
  50% { margin-left: 25%; margin-right: 0%; }
  100% { margin-left: 100%; margin-right: 0; }
}
@keyframes running-progress {
  0% { margin-left: 0px; margin-right: 100%; }
  50% { margin-left: 25%; margin-right: 0%; }
  100% { margin-left: 100%; margin-right: 0; }
}